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

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))上;并且应用程序部队关闭。 所以我的问题是 - 为什么会发生这种情况?什么是解释?我想我一定会错过一些大好时机。谢谢!

+1

可能有例外。您应该显示回溯的更多细节,但我想设置适配器只能在主线程上完成(如许多GUI操作) –

+0

您的适配器应该设置在'onPostExecute'中。你为什么要在'doInBackground'中设置它?你会从中得到什么好处? – Androiderson

+0

@ Exception-al没有什么特别的原因,但是在我在doInBackground中调用的函数中完成所有操作之前,我只是想知道。 – Fygo

gridview是一个UI元素,你不能更新在后台ThreadUI这是你与setAdapter()做什么,这就是为什么它在onPostExecute()

AsyncTask运行在UI Thread除了doInBackground()所有方法,这样是不能更新UI元素只有一个。所以如果你在onPostExecute()中设置它有问题,那么请解释它是什么,尽管你说它是有效的。如果没有问题,那就把它设置在那里。

AsyncTask Docs

+0

是的,它在onPostExecute中工作,它只是不清楚为什么。感谢您的解释。 – Fygo