首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 平面设计 > 图形图像 >

正确的在GridView中使用Bit地图图像

2013-03-27 
正确的在GridView中使用Bitmap图像欢迎访问:(IT开源学习)http://www.3body.tk/iblog/上面一篇文章《正确的

正确的在GridView中使用Bitmap图像

欢迎访问:(IT开源学习)http://www.3body.tk/iblog/

上面一篇文章《正确的在ViewPager中使用Bitmap图像》介绍了如何在ViewPager中加载bitmap图像。本篇将讲述如何将此技术用在GridView中。

使用列表来显示一组图像是十分有用的,你可以使用GridList控件来实现这个功能,你可以每次只显示一屏图像,其他的图像在用户做上下滚动操作的时候才会显示。实现这种控件的时候,你要确保UI元素流畅,内存不会超出最大限制,并且还要注意同步问题。

首先,我们以一个标准的使用Fragment包含ImageView的GridView实现。下面的实现看上去是十分理想的,你能看出怎样可以去优化它吗?

public class ImageGridFragment extends Fragment implements AdapterView.OnItemClickListener {    private ImageAdapter mAdapter;    // A static dataset to back the GridView adapter    public 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 docs    public ImageGridFragment() {}    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        mAdapter = new ImageAdapter(getActivity());    }    @Override    public 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;    }    @Override    public 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;        }        @Override        public int getCount() {            return imageResIds.length;        }        @Override        public Object getItem(int position) {            return imageResIds[position];        }        @Override        public long getItemId(int position) {            return position;        }        @Override        public View getView(int position, View convertView, ViewGroup container) {            ImageView imageView;            if (convertView == null) { // if it's not recycled, initialize some attributes                imageView = 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 ImageView            return imageView;        }    }}

与上篇文章《正确的在ViewPager中使用Bitmap图像》中的问题一样,这里的图像都是在UI线程中加载的。如果你的图片都很小可能不会出现问题,但是如果加入更多处理的话你的UI线程还是会悲剧的挂掉。

在上个文章中使用的异步和缓存机制同样适用于此。但是,你要多考虑一下同步的问题,因为GridView会自动回收它包含的子View。要解决这个问题,我们可以使用在《Processing Bitmaps Off the UI Thread》这一课中学到的方法。下面是解决方法:

public class ImageGridFragment extends Fragment implements AdapterView.OnItemClickListener {    ...    private class ImageAdapter extends BaseAdapter {        ...        @Override        public 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 task                bitmapWorkerTask.cancel(true);            } else {                // The same work is already in progress                return false;            }        }        // No task associated with the ImageView, or an existing task was cancelled        return 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

注意:上面的代码同样适用于ListView控件。

这个实现能够让你任意的处理和加载图片,并不会影响到UI的效果。在后台线程中你可以从网络上下载图片,或者裁剪从相机中导入的过大的照片,后台任务完成后才将图片显示出来。

翻译自:Displaying Bitmaps in Your UI

热点排行