概述
上一篇文章介绍了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,其他的都是逻辑很处理的问题。
如果我的文章对你有帮助,欢迎关注我~