Android:AsyncTask - 无法在doInBackground中设置适配器?

时间:2013-08-21 22:02:55

标签: java android android-asynctask forceclose

我对此感到有点困惑,所以我真的很感激有人的帮助。

我有一个活动 - 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内部(返回true语句的正上方)时,代码挂起在gridview.setAdapter(new ImageAdapter(activity));并且app力关闭。 所以我的问题是 - 为什么会这样?解释是什么?我想我一定会错过很多时间。谢谢!

1 个答案:

答案 0 :(得分:2)

gridview是一个UI元素,您无法更新背景UI上的Thread,这就是您使用setAdapter()进行的操作为什么它适用于onPostExecute()

AsyncTask的所有方法都在UI Thread上运行,doInBackground()除外,因此这是唯一一个无法更新UI元素的方法。因此,如果您在onPostExecute()中设置它时遇到问题,请说明它是什么,尽管您说它有效。如果没有问题,那就把它设置在那里。

AsyncTask Docs