AsyncTask offers an easy-to-use (but more limited).
You need to perform an asynchronous job that follows a pre-process/process/postprocess pattern, and are looking for a code template that allows you to report progress
to the user or otherwise update the UI in each step.
In the last technique, we retrieved movie thumbnail images by having a simple downloader helper method fork a new thread that downloaded the image, and then passed it to a custom handler object that updated the image on the list view.
create the AsyncTask class DownloadTask:
public class DownloadTask extends AsyncTask<String,Void,Bitmap> { private int position; private ImageView imageView; private Drawable placeholder; public DownloadTask(int position,ImageView imageView){ this.position=position; this.imageView=imageView; Resources resources=imageView.getContext().getResources(); this.placeholder=resources.getDrawable(android.R.drawable.gallery_thumb); } //Called before task runs protected void onPreExecute(){ imageView.setImageDrawable(placeholder); } //task logic protected Bitmap doInBackground(String... inputUrls) { try{ URL url=new URL(inputUrls[0]); return BitmapFactory.decodeStream(url.openStream()); }catch(Exception e){ e.printStackTrace(); return null; } } //called after task runs protected void onPostExecute(Bitmap result){ int forPosition=(Integer)imageView.getTag(); if(forPosition==this.position){ this.imageView.setImageBitmap(result); } } }worker arguments (String), worker progress (Void), and worker result (Bitmap).
trigger the task,modify the class MovieAdapter:
/** * Another perfectly valid approach would be to create a Movie model class. * get rid of the HashMap. */ //The MovieAdapter keeps track of selected movies //Adapter separating data from its representation on the screen public class MovieAdapter extends ArrayAdapter<String> { //storing movie state data //this state is transient private HashMap<Integer,Boolean> movieCollection=new HashMap<Integer,Boolean>(); private String[] movieIconUrls;//List of movie image URLs private ThreadPoolExecutor executor;//Controls thread pool public MovieAdapter(Context context) { super(context,R.layout.movie_item,android.R.id.text1,context.getResources().getStringArray(R.array.movies)); // TODO Auto-generated constructor stub //Read image URLs into array movieIconUrls=context.getResources().getStringArray(R.array.movie_thumbs); } public void toggleMovie(int position){ if(!isInCollection(position)){ movieCollection.put(position, true); } else{ movieCollection.put(position, false); } } public boolean isInCollection(int position){ return movieCollection.get(position) == Boolean.TRUE; } @Override //returns the view needed for each item. //cache and reuse item views via convertView for performance reasons public View getView(int position,View convertView,ViewGroup parent){ View listItem=super.getView(position, convertView, parent); CheckedTextView checkMark=(CheckedTextView)listItem.findViewById(android.R.id.text1); checkMark.setChecked(isInCollection(position)); ImageView imageView =(ImageView)listItem.findViewById(R.id.movie_icon); imageView.setImageDrawable(null); imageView.setTag(position);//link position to image view String imageUrl=movieIconUrls[position]; new DownloadTask(position,imageView).execute(imageUrl); return listItem; } }first, the absence of any explicit interthread communication using handlers and messages, and second, a higher code quality achieved by having all code related to the download task in a single class.