ArrayList未从AsyncTask正确填充

时间:2012-10-09 13:23:39

标签: android android-listview android-asynctask android-arrayadapter

我有一个从网络服务填充ArrayList的应用。从AsyncTask调用Web服务。当我在onPostExecute中测试时,将填充ArrayList。 ArrayList被定义为实例变量。为什么在AsyncTask完成时填充了arrayList,但是当我自己测试实例变量后,它就是null。似乎Async没有正确设置值。

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

}

}

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

让ListView成为课程中的一个字段,然后

使用

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

onPostExecute(字符串结果)方法

但我推荐的是:

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

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

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

<强> 1。创建数组

<强> 2。检查onCreate // 0中的长度,因为尚未添加任何内容

第3。在后台添加数据到数组

<强> 4。在onPostExecute(字符串结果)//实际长度

中检查其长度