Android 使用Loader轻松实现仿微信图片加载

概述

上一篇文章介绍了Loader的作用和相关知识,说白了Loader就是Android提供给我们用来更容易查询数据用的。其实在我们应用中查询数据最常用的应该就是查询手机的图片进行显示。今天就来学习一下使用Loader做一个简单的本地图片库,类似于微信的图片选择。先来看看效果图:

福利来了!
这里写图片描述

由于图片上传大小有限制,所以只有一点效果,大家可以在最后下载源码自己体验,就算快速滑动也马上就能显示。
对Loader还没有了解的同学可以去看上一篇文章: Android Loader解析

要做一个这样的图片浏览其实很简单,利用Loader把手机里所有图片查询出来,再使用GridView进行展示就行了。就是那么简单。

实现步骤

1、建一个用来查询和展示图片的Activity,在onCreate中初始化Loader,并且在回调LoaderCallbacks的回调方法中进行处理。

public class ImageGridActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {


    private final String[] IMAGE_PROJECTION = {
            MediaStore.Images.Media.DATA,
            MediaStore.Images.Media.DISPLAY_NAME,
            MediaStore.Images.Media.DATE_ADDED,
            MediaStore.Images.Media._ID };

    // different loader define
    public static final int LOADER_ALL = 0;
    public static final int LOADER_CATEGORY = 1;
    private ArrayList<ImageSet> mImageSetList = new ArrayList<>();

    int imageGridSize;
    GridView mGridView;//进行图片展示的GridView

    ImageGridAdapter mAdapter;//图片展示的Adapter



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image_grid);

        imageGridSize = (getWindowManager().getDefaultDisplay().getWidth() - Util.dp2px(this, 2) * 2) / 3;
        //根据屏幕宽度获取到item显示的大小
        mGridView = (GridView) findViewById(R.id.image_grid);


        getLoaderManager().initLoader(0,null,this);//初始化Loader,LoaderManager会回调onCreateLoader去获取一个Loader,并且在查询结束的时候回调onLoadFinished
    }

    @Override
    public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {

            //创建了一个CursorLoader,查询的数据有文件地址,名次,添加时间,id并且按照添加时间排序
            CursorLoader cursorLoader =  new CursorLoader(this, MediaStore.Images.Media.EXTERNAL_CONTENT_URI,IMAGE_PROJECTION,null,null,IMAGE_PROJECTION[2]+" DESC ");
            return cursorLoader;
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        //获取到查询的所有图片信息,并且设置到adapter总进行图片显示
        if (data!=null){
            List<ImageItem> allImages = new ArrayList<>();
            int count = data.getCount();
            if (count <= 0){
                return;
            }
            data.moveToFirst();
            do {
                String imagePath = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[0]));
                String imageName = data.getString(data.getColumnIndexOrThrow(IMAGE_PROJECTION[1]));
                long imageAddedTime = data.getLong(data.getColumnIndexOrThrow(IMAGE_PROJECTION[2]));

                ImageItem item = new ImageItem(imagePath,imageName,imageAddedTime);
                allImages.add(item);

            }while (data.moveToNext());
            mAdapter = new ImageGridAdapter(this,allImages);
            mGridView.setAdapter(mAdapter);

        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {

    }

}

上面代码都给了注释,很好理解。在onLoadFinished中查询到图片信息,并且将图片信息封装到ImageItem实体类中。添加到List。最后简单设置一下数据适配器

2、查询到图片信息之后,就是需要显示出来,接下来看一下适配器的代码:

class ImageGridAdapter extends BaseAdapter {
        List<ImageItem> images;
        Context mContext;

        public ImageGridAdapter(Context ctx, List<ImageItem> images) {
            this.images = images;
            this.mContext = ctx;
        }

        @Override
        public int getCount() {
            return  images.size();
        }

        @Override
        public ImageItem getItem(int position) {
            return images.get(position);

        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {

            final ViewHolder holder;
            if (convertView == null) {
                convertView = LayoutInflater.from(mContext).inflate(R.layout.image_grid_item, null);
                holder = new ViewHolder();
                holder.ivPic = (ImageView) convertView.findViewById(R.id.iv_thumb);
                holder.cbSelected = (SuperCheckBox) convertView.findViewById(R.id.iv_thumb_check);
                holder.cbPanel = convertView.findViewById(R.id.thumb_check_panel);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }

            final ImageItem item = getItem(position);


            ViewGroup.LayoutParams params = holder.ivPic.getLayoutParams();
            params.width = params.height = imageGridSize;

            Picasso.with(holder.ivPic.getContext())
                    .load(new File(item.path))
                    .centerCrop()
                    .resize(imageGridSize/4*3, imageGridSize/4*3)
                    .placeholder(R.drawable.default_img)
                    .into(holder.ivPic);
            return convertView;

        }

        class ViewHolder {
            ImageView ivPic;
            SuperCheckBox cbSelected;
            View cbPanel;
        }

        public void refreshData(List<ImageItem> items) {
            if (items != null && items.size() > 0) {
                images = items;
            }
            notifyDataSetChanged();
        }

    }

上面的代码是一个ListView GridView数据渲染的常见写法,相信大家很熟悉了,在getView中获取到图片,通过Picasso来进行本地图片的展示。

总结

上面的例子,通过Loader加载数据的代码其实不过10多行,其他的代码大部分是数据渲染展示。可见Android提供的Loader异步数据查询工具类是多么的强大!那么大家可以用Loader来自己实现一个类似微信的图片选择。有了Loader,其他的都是逻辑很处理的问题。

如果我的文章对你有帮助,欢迎关注我~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员yqy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值