日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

Android官方开发文档Training系列课程中文版:高效显示位图之在UI中展示位图

發(fā)布時(shí)間:2024/7/5 Android 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android官方开发文档Training系列课程中文版:高效显示位图之在UI中展示位图 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

原文地址:http://android.xsoftlab.net/training/displaying-bitmaps/display-bitmap.html

這節(jié)課會(huì)將前面的知識(shí)點(diǎn)整合到一起,展示如何使用后臺(tái)線程、位圖緩存來加載多張圖片到ViewPager或者GridView中,并會(huì)涉及并發(fā)處理及配置更改的相關(guān)知識(shí)。

加載位圖到ViewPager

swipe view pattern是畫廊應(yīng)用詳情頁(yè)之間來回跳轉(zhuǎn)的最佳演示。你可以使用ViewPager來實(shí)現(xiàn)這種模式。無論如何,FragmentStatePagerAdapter是ViewPager支撐適配器的最佳選擇,它可以隨著Fragment在屏幕上的消失自動(dòng)銷毀與保存Fragment的狀態(tài),降低內(nèi)存的使用。

Note: 如果你有少量的圖片并且可以保證它們一起被加入內(nèi)存之后不會(huì)超出內(nèi)存的限制,那么使用正規(guī)的PagerAdapter或者FragmentPagerAdapter可能更合適些。

下面是帶有ImageView的ViewPager實(shí)現(xiàn)。MainActivity持有了ViewPager及Adapter的引用:

public class ImageDetailActivity extends FragmentActivity {public static final String EXTRA_IMAGE = "extra_image";private ImagePagerAdapter mAdapter;private ViewPager mPager;// A static dataset to back the ViewPager adapterpublic final static Integer[] imageResIds = new Integer[] {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};@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.image_detail_pager); // Contains just a ViewPagermAdapter = new ImagePagerAdapter(getSupportFragmentManager(), imageResIds.length);mPager = (ViewPager) findViewById(R.id.pager);mPager.setAdapter(mAdapter);}public static class ImagePagerAdapter extends FragmentStatePagerAdapter {private final int mSize;public ImagePagerAdapter(FragmentManager fm, int size) {super(fm);mSize = size;}@Overridepublic int getCount() {return mSize;}@Overridepublic Fragment getItem(int position) {return ImageDetailFragment.newInstance(position);}} }

下面是詳情Fragment的實(shí)現(xiàn),它持有了ImageView的引用。這可能看起來是一種非常合理的方式,但是你可以看出這個(gè)實(shí)現(xiàn)的缺陷嗎?如何改進(jìn)它?

public class ImageDetailFragment extends Fragment {private static final String IMAGE_DATA_EXTRA = "resId";private int mImageNum;private ImageView mImageView;static ImageDetailFragment newInstance(int imageNum) {final ImageDetailFragment f = new ImageDetailFragment();final Bundle args = new Bundle();args.putInt(IMAGE_DATA_EXTRA, imageNum);f.setArguments(args);return f;}// Empty constructor, required as per Fragment docspublic ImageDetailFragment() {}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mImageNum = getArguments() != null ? getArguments().getInt(IMAGE_DATA_EXTRA) : -1;}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {// image_detail_fragment.xml contains just an ImageViewfinal View v = inflater.inflate(R.layout.image_detail_fragment, container, false);mImageView = (ImageView) v.findViewById(R.id.imageView);return v;}@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);final int resId = ImageDetailActivity.imageResIds[mImageNum];mImageView.setImageResource(resId); // Load image into ImageView} }

希望你會(huì)注意到這個(gè)問題:讀取圖片資源的過程是在UI線程中執(zhí)行的,這會(huì)導(dǎo)致程序的卡頓及被強(qiáng)制關(guān)閉。使用在Processing Bitmaps Off the UI Thread課程中所描述的AsyncTask,它可以簡(jiǎn)單的將圖片的加載與處理過程交給后臺(tái)線程:

public class ImageDetailActivity extends FragmentActivity {...public void loadBitmap(int resId, ImageView imageView) {mImageView.setImageResource(R.drawable.image_placeholder);BitmapWorkerTask task = new BitmapWorkerTask(mImageView);task.execute(resId);}... // include BitmapWorkerTask class } public class ImageDetailFragment extends Fragment {...@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);if (ImageDetailActivity.class.isInstance(getActivity())) {final int resId = ImageDetailActivity.imageResIds[mImageNum];// Call out to ImageDetailActivity to load the bitmap in a background thread((ImageDetailActivity) getActivity()).loadBitmap(resId, mImageView);}} }

任何額外的處理,比如調(diào)整圖片尺寸或者從網(wǎng)絡(luò)獲取圖像,這些處理過程可以放入BitmapWorkerTask而不會(huì)影響到主線程的響應(yīng)能力。如果后臺(tái)線程做的不僅僅是從磁盤上直接加載圖像,那么它還益于處理添加內(nèi)存緩存及磁盤緩存。下面是針對(duì)于內(nèi)存緩存的專門修改版本:

public class ImageDetailActivity extends FragmentActivity {...private LruCache<String, Bitmap> mMemoryCache;@Overridepublic void onCreate(Bundle savedInstanceState) {...// initialize LruCache as per Use a Memory Cache section}public void loadBitmap(int resId, ImageView imageView) {final String imageKey = String.valueOf(resId);final Bitmap bitmap = mMemoryCache.get(imageKey);if (bitmap != null) {mImageView.setImageBitmap(bitmap);} else {mImageView.setImageResource(R.drawable.image_placeholder);BitmapWorkerTask task = new BitmapWorkerTask(mImageView);task.execute(resId);}}... // include updated BitmapWorkerTask from Use a Memory Cache section }

以最小的加載延遲將這些塊提供給ViewPager,并盡可能的將處理圖片的工作放入后臺(tái)線程。

加載位圖到GridView

grid list building block對(duì)展示圖片數(shù)據(jù)集很有幫助,它主要通過GridView來實(shí)現(xiàn),它可以將很多圖片在同一時(shí)間顯示出來,如果用戶要來回滑動(dòng),那可能會(huì)有更多的圖片需要準(zhǔn)備展示出來。當(dāng)實(shí)現(xiàn)這種控制類型時(shí),你必須確保UI依舊流暢,內(nèi)存的使用依舊在控制范圍之內(nèi),并發(fā)的處理依舊正確(因?yàn)镚ridView會(huì)回收它的子View)。

首先,這里有一個(gè)標(biāo)準(zhǔn)的GridView實(shí)現(xiàn)。再者,這可能看起來非常完美,但是它還有可以改進(jìn)的地方嗎?

public class ImageGridFragment extends Fragment implements AdapterView.OnItemClickListener {private ImageAdapter mAdapter;// A static dataset to back the GridView adapterpublic final static Integer[] imageResIds = new Integer[] {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 docspublic ImageGridFragment() {}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mAdapter = new ImageAdapter(getActivity());}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {final View v = inflater.inflate(R.layout.image_grid_fragment, container, false);final GridView mGridView = (GridView) v.findViewById(R.id.gridView);mGridView.setAdapter(mAdapter);mGridView.setOnItemClickListener(this);return v;}@Overridepublic void onItemClick(AdapterView<?> parent, View v, int position, long id) {final Intent i = new Intent(getActivity(), ImageDetailActivity.class);i.putExtra(ImageDetailActivity.EXTRA_IMAGE, position);startActivity(i);}private class ImageAdapter extends BaseAdapter {private final Context mContext;public ImageAdapter(Context context) {super();mContext = context;}@Overridepublic int getCount() {return imageResIds.length;}@Overridepublic Object getItem(int position) {return imageResIds[position];}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup container) {ImageView imageView;if (convertView == null) { // if it's not recycled, initialize some attributesimageView = new ImageView(mContext);imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);imageView.setLayoutParams(new GridView.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));} else {imageView = (ImageView) convertView;}imageView.setImageResource(imageResIds[position]); // Load image into ImageViewreturn imageView;}} }

再提示一次,這個(gè)實(shí)現(xiàn)的問題圖像的設(shè)置過程位于UI線程。雖然這可能只是應(yīng)用小圖像、簡(jiǎn)單圖像,但如果有任何的額外工作需要處理,那么UI線程就會(huì)戛然而止。

前一節(jié)中的一步處理及緩存圖像可以實(shí)現(xiàn)到這里。無論如何,你還需要對(duì)由GridView所引起的并發(fā)問題提高警惕。如果要處理這個(gè)問題,可以使用在Processing Bitmaps Off the UI Thread課程中所提到的技巧。下面是更改后的版本:

public class ImageGridFragment extends Fragment implements AdapterView.OnItemClickListener {...private class ImageAdapter extends BaseAdapter {...@Overridepublic View getView(int position, View convertView, ViewGroup container) {...loadBitmap(imageResIds[position], imageView)return imageView;}}public void loadBitmap(int resId, ImageView imageView) {if (cancelPotentialWork(resId, imageView)) {final BitmapWorkerTask task = new BitmapWorkerTask(imageView);final AsyncDrawable asyncDrawable =new AsyncDrawable(getResources(), mPlaceHolderBitmap, task);imageView.setImageDrawable(asyncDrawable);task.execute(resId);}}static class AsyncDrawable extends BitmapDrawable {private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;public AsyncDrawable(Resources res, Bitmap bitmap,BitmapWorkerTask bitmapWorkerTask) {super(res, bitmap);bitmapWorkerTaskReference =new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);}public BitmapWorkerTask getBitmapWorkerTask() {return bitmapWorkerTaskReference.get();}}public static boolean cancelPotentialWork(int data, ImageView imageView) {final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);if (bitmapWorkerTask != null) {final int bitmapData = bitmapWorkerTask.data;if (bitmapData != data) {// Cancel previous taskbitmapWorkerTask.cancel(true);} else {// The same work is already in progressreturn false;}}// No task associated with the ImageView, or an existing task was cancelledreturn true;}private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {if (imageView != null) {final Drawable drawable = imageView.getDrawable();if (drawable instanceof AsyncDrawable) {final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;return asyncDrawable.getBitmapWorkerTask();}}return null;}... // include updated BitmapWorkerTask class

Note: 上面的代碼也可以應(yīng)用于ListView。

這個(gè)實(shí)現(xiàn)對(duì)如何處理及加載圖像是很靈活的,并不會(huì)妨礙UI的流暢性。后臺(tái)任務(wù)可以從網(wǎng)絡(luò)加載圖像并且可以調(diào)整數(shù)碼相片的尺寸,并會(huì)在任務(wù)結(jié)束的時(shí)候提供處理后的圖像。

對(duì)于本示例的全部代碼以及這節(jié)課中討論到的其它概念,可以查看包含這部分功能的示例應(yīng)用。

總結(jié)

以上是生活随笔為你收集整理的Android官方开发文档Training系列课程中文版:高效显示位图之在UI中展示位图的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。