Android:AsyncTask - 无法在doInBackground中设置适配器?
我对此有点困惑,所以我会很感激有人的帮助。Android:AsyncTask - 无法在doInBackground中设置适配器?
我有一个活动 - MainActivity,在活动内部我有两个类 - RetrieveThumbnailsTask(AsyncTask)和一个适配器ImageAdapter(扩展了BaseAdapter)。我基本上只是从外部存储检索图像的缩略图,并在gridview中显示它们。现在这证明是非常慢的(对于数百张图片需要相当长的时间),所以我决定在AsyncTask中创建缩略图。
的代码是/不相关的部分排除在外/:
public class MainActivity extends Activity {
private Cursor cursor;
private Bitmap[] thumbnails;
private ProgressDialog pd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
createProgressDialog();
new RetrieveThumbnailsTask(this).execute();
}
private void createProgressDialog() {
//...
}
private void createThumbnails() {
//...
}
private class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return thumbnails.length;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) { // if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(120, 120));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
}
else {
imageView = (ImageView) convertView;
}
imageView.setImageBitmap(thumbnails[position]);
return imageView;
}
}
private class RetrieveThumbnailsTask extends AsyncTask<Void, Void, Boolean> {
private MainActivity activity;
public RetrieveThumbnailsTask(MainActivity a) {
activity = a;
}
protected void onPreExecute() {
pd.show();
}
protected Boolean doInBackground(Void... params) {
activity.createThumbnails(); //This is the slow process that creates the thumbnails
return true;
}
protected void onPostExecute(Boolean b) {
pd.dismiss();
GridView gridview = (GridView) findViewById(R.id.gridview);
gridview.setAdapter(new ImageAdapter(activity));
gridview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
Toast.makeText(MainActivity.this, "" + position, Toast.LENGTH_SHORT).show();
}
});
}
}
}
我不明白的部分是这样的:
GridView gridview = (GridView) findViewById(R.id.gridview);
gridview.setAdapter(new ImageAdapter(activity));
gridview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
Toast.makeText(MainActivity.this, "" + position, Toast.LENGTH_SHORT).show();
}
});
现在,当这个代码是onPostExecute内,一切工作正常的。但是,当它位于doInBackground(正好在return true语句之上)时,代码会挂在gridview.setAdapter(new ImageAdapter(activity))上;并且应用程序部队关闭。 所以我的问题是 - 为什么会发生这种情况?什么是解释?我想我一定会错过一些大好时机。谢谢!
gridview
是一个UI
元素,你不能更新在后台Thread
的UI
这是你与setAdapter()
做什么,这就是为什么它在onPostExecute()
。
AsyncTask
运行在UI Thread
除了doInBackground()
所有方法,这样是不能更新UI
元素只有一个。所以如果你在onPostExecute()
中设置它有问题,那么请解释它是什么,尽管你说它是有效的。如果没有问题,那就把它设置在那里。
是的,它在onPostExecute中工作,它只是不清楚为什么。感谢您的解释。 – Fygo
可能有例外。您应该显示回溯的更多细节,但我想设置适配器只能在主线程上完成(如许多GUI操作) –
您的适配器应该设置在'onPostExecute'中。你为什么要在'doInBackground'中设置它?你会从中得到什么好处? – Androiderson
@ Exception-al没有什么特别的原因,但是在我在doInBackground中调用的函数中完成所有操作之前,我只是想知道。 – Fygo