publicclassImageDetailActivityextendsFragmentActivity{publicstaticfinalStringEXTRA_IMAGE="extra_image";privateImagePagerAdaptermAdapter;privateViewPagermPager;// A static dataset to back the ViewPager adapter publicfinalstaticInteger[]imageResIds=newInteger[]{R.drawable.sample_image_1,R.drawable.sample_image_2,R.drawable.sample_image_3,R.drawable.sample_image_4,R.drawable.sample_image_5,R.drawable.sample_image_6,R.drawable.sample_image_7,R.drawable.sample_image_8,R.drawable.sample_image_9};@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.image_detail_pager);// Contains just a ViewPager mAdapter=newImagePagerAdapter(getSupportFragmentManager(),imageResIds.length);mPager=(ViewPager)findViewById(R.id.pager);mPager.setAdapter(mAdapter);}publicstaticclassImagePagerAdapterextendsFragmentStatePagerAdapter{privatefinalintmSize;publicImagePagerAdapter(FragmentManagerfm,intsize){super(fm);mSize=size;}@OverridepublicintgetCount(){returnmSize;}@OverridepublicFragmentgetItem(intposition){returnImageDetailFragment.newInstance(position);}}}
publicclassImageDetailFragmentextendsFragment{privatestaticfinalStringIMAGE_DATA_EXTRA="resId";privateintmImageNum;privateImageViewmImageView;staticImageDetailFragmentnewInstance(intimageNum){finalImageDetailFragmentf=newImageDetailFragment();finalBundleargs=newBundle();args.putInt(IMAGE_DATA_EXTRA,imageNum);f.setArguments(args);returnf;}// Empty constructor, required as per Fragment docs publicImageDetailFragment(){}@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);mImageNum=getArguments()!=null?getArguments().getInt(IMAGE_DATA_EXTRA):-1;}@OverridepublicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,BundlesavedInstanceState){// image_detail_fragment.xml contains just an ImageView finalViewv=inflater.inflate(R.layout.image_detail_fragment,container,false);mImageView=(ImageView)v.findViewById(R.id.imageView);returnv;}@OverridepublicvoidonActivityCreated(BundlesavedInstanceState){super.onActivityCreated(savedInstanceState);finalintresId=ImageDetailActivity.imageResIds[mImageNum];mImageView.setImageResource(resId);// Load image into ImageView }}
publicclassImageDetailActivityextendsFragmentActivity{...publicvoidloadBitmap(intresId,ImageViewimageView){mImageView.setImageResource(R.drawable.image_placeholder);BitmapWorkerTasktask=newBitmapWorkerTask(mImageView);task.execute(resId);}...// include BitmapWorkerTask class }publicclassImageDetailFragmentextendsFragment{...@OverridepublicvoidonActivityCreated(BundlesavedInstanceState){super.onActivityCreated(savedInstanceState);if(ImageDetailActivity.class.isInstance(getActivity())){finalintresId=ImageDetailActivity.imageResIds[mImageNum];// Call out to ImageDetailActivity to load the bitmap in a background thread ((ImageDetailActivity)getActivity()).loadBitmap(resId,mImageView);}}}
在 BitmapWorkerTask 中做一些例如resizing or fetching images from the network,不会卡到UI Thread。如果后台线程不仅仅是做个简单的直接加载动作,增加一个内存Cache或者磁盘Cache会比较好[参考Lesson 3] ,下面是一些为了内存Cache而附加的内容:
12345678910111213141516171819202122232425
publicclassImageDetailActivityextendsFragmentActivity{...privateLruCachemMemoryCache;@OverridepublicvoidonCreate(BundlesavedInstanceState){...// initialize LruCache as per Use a Memory Cache section }publicvoidloadBitmap(intresId,ImageViewimageView){finalStringimageKey=String.valueOf(resId);finalBitmapbitmap=mMemoryCache.get(imageKey);if(bitmap!=null){mImageView.setImageBitmap(bitmap);}else{mImageView.setImageResource(R.drawable.image_placeholder);BitmapWorkerTasktask=newBitmapWorkerTask(mImageView);task.execute(resId);}}...// include updated BitmapWorkerTask from Use a Memory Cache section }
Load Bitmaps into a GridView Implementation(实现加载图片到GridView)
Grid list building block 是一种有效显示大量图片的方式。这样能够一次显示许多图片,而且那些即将被显示的图片也处于准备显示状态。如果你想要实现这种效果,你必须确保UI是流畅的,能够控制内存使用,并且正确的处理并发问题(因为 GridView 会循环使用子视图)。
publicclassImageGridFragmentextendsFragmentimplementsAdapterView.OnItemClickListener{privateImageAdaptermAdapter;// A static dataset to back the GridView adapter publicfinalstaticInteger[]imageResIds=newInteger[]{R.drawable.sample_image_1,R.drawable.sample_image_2,R.drawable.sample_image_3,R.drawable.sample_image_4,R.drawable.sample_image_5,R.drawable.sample_image_6,R.drawable.sample_image_7,R.drawable.sample_image_8,R.drawable.sample_image_9};// Empty constructor as per Fragment docs publicImageGridFragment(){}@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);mAdapter=newImageAdapter(getActivity());}@OverridepublicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,BundlesavedInstanceState){finalViewv=inflater.inflate(R.layout.image_grid_fragment,container,false);finalGridViewmGridView=(GridView)v.findViewById(R.id.gridView);mGridView.setAdapter(mAdapter);mGridView.setOnItemClickListener(this);returnv;}@OverridepublicvoidonItemClick(AdapterViewparent,Viewv,intposition,longid){finalIntenti=newIntent(getActivity(),ImageDetailActivity.class);i.putExtra(ImageDetailActivity.EXTRA_IMAGE,position);startActivity(i);}privateclassImageAdapterextendsBaseAdapter{privatefinalContextmContext;publicImageAdapter(Contextcontext){super();mContext=context;}@OverridepublicintgetCount(){returnimageResIds.length;}@OverridepublicObjectgetItem(intposition){returnimageResIds[position];}@OverridepubliclonggetItemId(intposition){returnposition;}@OverridepublicViewgetView(intposition,ViewconvertView,ViewGroupcontainer){ImageViewimageView;if(convertView==null){// if it's not recycled, initialize some attributes imageView=newImageView(mContext);imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);imageView.setLayoutParams(newGridView.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));}else{imageView=(ImageView)convertView;}//请注意下面的代码 imageView.setImageResource(imageResIds[position]);// Load image into ImageView returnimageView;}}
publicclassImageGridFragmentextendsFragmentimplementsAdapterView.OnItemClickListener{...privateclassImageAdapterextendsBaseAdapter{...@OverridepublicViewgetView(intposition,ViewconvertView,ViewGroupcontainer){...loadBitmap(imageResIds[position],imageView)returnimageView;}}publicvoidloadBitmap(intresId,ImageViewimageView){if(cancelPotentialWork(resId,imageView)){finalBitmapWorkerTasktask=newBitmapWorkerTask(imageView);finalAsyncDrawableasyncDrawable=newAsyncDrawable(getResources(),mPlaceHolderBitmap,task);imageView.setImageDrawable(asyncDrawable);task.execute(resId);}}staticclassAsyncDrawableextendsBitmapDrawable{privatefinalWeakReferencebitmapWorkerTaskReference;publicAsyncDrawable(Resourcesres,Bitmapbitmap,BitmapWorkerTaskbitmapWorkerTask){super(res,bitmap);bitmapWorkerTaskReference=newWeakReference(bitmapWorkerTask);}publicBitmapWorkerTaskgetBitmapWorkerTask(){returnbitmapWorkerTaskReference.get();}}publicstaticbooleancancelPotentialWork(intdata,ImageViewimageView){finalBitmapWorkerTaskbitmapWorkerTask=getBitmapWorkerTask(imageView);if(bitmapWorkerTask!=null){finalintbitmapData=bitmapWorkerTask.data;if(bitmapData!=data){// Cancel previous task bitmapWorkerTask.cancel(true);}else{// The same work is already in progress returnfalse;}}// No task associated with the ImageView, or an existing task was cancelled returntrue;}privatestaticBitmapWorkerTaskgetBitmapWorkerTask(ImageViewimageView){if(imageView!=null){finalDrawabledrawable=imageView.getDrawable();if(drawableinstanceofAsyncDrawable){finalAsyncDrawableasyncDrawable=(AsyncDrawable)drawable;returnasyncDrawable.getBitmapWorkerTask();}}returnnull;}...// include updated BitmapWorkerTask class