0

我有一个ArrayList从网络服务填充的应用程序。Web 服务是从AsyncTask. 当我在onPostExecute. ArrayList 被定义为实例变量。为什么当 AsyncTask 完成时填充了 arrayList 但是当我之后测试实例变量本身时,它为空。似乎 Async 没有正确设置值。

异步完成后,我将 ArrayList 传递给 arrayAdapter,但我的 listView 为空。

测试:在onPostExecute

 Log.e(TAG, "array from WS = " + array.size());  // returns 4

测试:在onCreate

 Log.e(TAG, "checking to see if array is null " + array.size()); // returns 0



 package com.carefreegroup;

 public class GetRotaDetails extends NfcBaseActivity implements OnItemClickListener
 {
ArrayList<ArrayList<String>> array;
MySimpleArrayAdapter arrayAdapter;
Intent intent;
private static final String TAG = GetRotaDetails.class.getSimpleName();
ListView listView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    array = new  ArrayList<ArrayList<String>>();
    nfcscannerapplication = (NfcScannerApplication) getApplication();
    intent = this.getIntent();
    setContentView(R.layout.getrotadetailslayout);
    listView = (ListView) findViewById(R.id.getrotadetailslistview);

    //set titlebar to carer's name
    Cursor cursorCarerName = nfcscannerapplication.loginValidate.queryAllFromCarer();
    cursorCarerName.moveToLast();
    String carerTitleName = cursorCarerName.getString(cursorCarerName
            .getColumnIndex(LoginValidate.C_CARER_NAME));
    setTitle(carerTitleName + " is currently logged in");

    callID = intent.getStringExtra("callIDExtra");
    Log.e(TAG, "callID = " + callID);
    String[] params = { callID };
    AsyncGetRotaDetails agrd = new AsyncGetRotaDetails();
    agrd.execute(params);

    Log.e(TAG, "checking to see if array is null " + array.size());
    if (arrayAdapter == null){
        MySimpleArrayAdapter arrayAdapter = new MySimpleArrayAdapter(this, array);
        listView.setAdapter(arrayAdapter);
    }
    listView.setAdapter(arrayAdapter);
    listView.setOnItemClickListener(this);


}// end of onCreate

@Override
protected void onResume() {


    super.onResume();
}


private class AsyncGetRotaDetails extends AsyncTask<String, Void, String> {

    ProgressDialog progressDialog;
    String rotaDetails = null;

    @Override
    protected void onPreExecute() {
        progressDialog = ProgressDialog
                .show(GetRotaDetails.this, "Connecting to Server",
                        " retrieving rota details...", true);

    };

    @Override
    protected String doInBackground(String... params) { 

        try {
            Log.e(TAG, "inside doInBackground");

            rotaDetails = nfcscannerapplication.loginWebservice.getRotaDetail(params[0]);

        } catch (Exception e) {

            e.printStackTrace();

        }
        return rotaDetails;

    }

    @Override
    protected void onPostExecute(String xmlResult) {
        super.onPostExecute(xmlResult);
        if (progressDialog != null)
            progressDialog.dismiss();

        if (rotaDetails != null) {



            RetrieveExtraDetails red = new RetrieveExtraDetails();
           array = red.getExtraDetails(xmlResult);
            Log.e(TAG, "array from WS = " + array.size());

        } else {

            AlertDialog alertDialog = new AlertDialog.Builder(
                    GetRotaDetails.this).create();
            alertDialog.setTitle("Signal/Server Test");
            alertDialog.setMessage("No Phone Signal or Server Problem");

            alertDialog.setButton("OK",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog,
                                int which) {

                            onStart();
                        }
                    });

            alertDialog.show();

        }

    }// end of postExecute

}//end of Async

private class MySimpleArrayAdapter extends ArrayAdapter<String> {



    private final Context context;
    private final ArrayList<?> list;

    public MySimpleArrayAdapter(Context context, ArrayList<?> list) {

        super(context, R.layout.getrotadetailsrow);
        Log.e(TAG, "inside adapter constructor");
        this.context = context;
        this.list = list;


    }// end of constructor

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View rowView = inflater.inflate(R.layout.getrotadetailsrow, parent,
                false);

        TextView recTypeID = (TextView) rowView
                .findViewById(R.id.rectypeid);

        TextView recType = (TextView) rowView
                .findViewById(R.id.rectype);

        TextView name = (TextView) rowView
                .findViewById(R.id.name);

        TextView relationship = (TextView) rowView
                .findViewById(R.id.relationship);

        TextView address = (TextView) rowView
                .findViewById(R.id.address);

        TextView postCode = (TextView) rowView
                .findViewById(R.id.postcode);

        TextView telNo = (TextView) rowView
                .findViewById(R.id.telno);

        TextView keySafe = (TextView) rowView
                .findViewById(R.id.keysafe);

        TextView notes = (TextView) rowView
                .findViewById(R.id.notes);

        TextView meds = (TextView) rowView
                .findViewById(R.id.meds);

        String record = list.get(position).toString();

        Log.e(TAG, "record = " + record);
        recTypeID.setText(record);
        return super.getView(position, convertView, parent);
    }

}

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    // TODO Auto-generated method stub

}

}
4

2 回答 2

2

实际上, AsyncTask 是异步运行的,它不是阻塞调用(就像在 onPostExecute() 执行之后返回的 execute() 方法一样)。因此,您需要在下载数据时在 onPostExecute() 中通知适配器。这是一个与多线程相关的问题,当执行execute() 行时,会为AsyncTask 创建一个线程,并且onCreate() 的执行移到下一行,因此同时,doInBackground() 和onCreate() 将在AsyncTask 线程和UI 中执行分别穿线。

于 2012-10-09T13:33:16.057 回答
0

使您的 ListView 成为班级中的一个字段,然后

采用

listView.setAdapter(arrayAdapter);
listView.setOnItemClickListener(this);

onPostExecute(String result)方法中

但我推荐的是:

使用加载微调器,直到获取数据并设置适配器,否则行为是 Activity 显示为空,并且在 3-5 秒后突然出现整个列表,这是一个糟糕的 UX。

通常,当获取的数据是 UI 的一小部分,而不是 UI 的主要组件 ListView 时,我们会使用没有任何加载微调器的异步任务。

并且不要在 onCreate() 中检查数组的长度。它将始终为 0。因为代码流将是:

1. 创建数组

2. 在 onCreate //0 中检查它的长度,因为还没有添加任何内容

3.后台添加数据到Array

4.在onPostExecute(String result) //实际长度中检查它的长度

于 2012-10-09T14:03:28.677 回答