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

标签 java android android-asynctask forceclose

我对此有点困惑,所以我非常感谢有人的帮助。

我有一个 Activity - MainActivity,在 Activity 内部我有两个类 - 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() 中工作的原因。

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

AsyncTask Docs

关于java - Android:AsyncTask - 无法在 doInBackground 中设置适配器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18368466/

相关文章:

Android首先检测双击而不是单击

java - 无法覆盖 doInBackground 方法 (asyncTask)

java - Android TTS 无法说出大量文字

java - 无法使用 Java 中的 Weka 访问 ML 分类的训练数据集

java - 如何覆盖 Spring Boot 2.0.x 中的默认连接池限制

android - 如何为Android编译并运行简单的C代码?

android - 无法使用 SimpleAdapter、ViewBinder 和 Asynctask 将图像从 ListView 设置到 ImageView

java - 在 JFrame 中移动立方体时显示 X Y 坐标

java - java.util.Currency 中的 getSymbol() 根据 API 级别返回不同的值

android - Android TabLayout Tabs Click 面临问题