我有一个从网络服务填充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
}
}
答案 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(字符串结果)//实际长度
中检查其长度