本篇文章主要介绍了"使用AsyncTaskLoader获取本地数据图片",主要涉及到更新UI,RelativeLayou,Parcelable,Activity,保存图片方面的内容,对于Android开发感兴趣的同学可以参考一下:
在项目中用到了AsyncTaskLoader来获取本地的图片,没错,就是它,不是AsyncTask;刚看见这个类的时候有些疑惑,想必它肯定和AsyncTask有...
在项目中用到了AsyncTaskLoader来获取本地的图片,没错,就是它,不是AsyncTask;刚看见这个类的时候有些疑惑,想必它肯定和AsyncTask有什么联系,于是网上查找了一些资料,其实它们最主要的区别就是:AsyncTaskLoader只用来获取数据,它不考虑和UI交互,而AsyncTask可以获取数据并将数据展示在UI上。于是,写了一个demo使用AsyncTaskLoader类来获取本地图片。废话少说,进入正题。
首先,需要获取一个加载器的管理对象,然后初始化加载器
getSupportLoaderManager().initLoader(0,null,this);
这通常在onCreate()方法中进行
initLoader的三个参数:
0代表加载器的唯一标识id
null指传递给加载器的参数,这里为null
this指实现了LoaderCallbacks接口的Activity(注意是v4包下面的LoaderCallbacks)
然后接着实现LoaderCallbacks接口的两个方法
/**
* 创建数据加载器
* @param id
* @param args
* @return
*/
@Override
public Loader<>> onCreateLoader(int id, Bundle args) {
return new ImagesLoader(this);
}
这个是返回带List
数据的加载器。 ImageBean是具体的数据,它实现了Parcelable接口,便于传递数据
而ImagesLoader就是继承AsyncTaskLoader类的获取本地图片数据的加载器
/**
* 数据加载完成之后的操作
* @param loader
* @param data
*/
@Override
public void onLoadFinished(Loader<>> loader, List data) {
mBeans.clear();
mBeans.addAll(data);
mAdapter.notifyDataSetChanged();
}
这个方法就是数据加载完成之后更新UI
最后就是ImagesLoader类的具体实现,继承AsyncTaskLoader,并实现关键的几个方法。直接上代码吧(代码是最好的老师)
package com.crazy.wang.net;
import android.content.Context;
import android.database.Cursor;
import android.provider.MediaStore;
import android.support.v4.content.AsyncTaskLoader;
import com.crazy.wang.model.ImageBean;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author Cloudsoar(wangyb)
* @datetime 2015-11-30 21:52 GMT+8
* @email 395044952@qq.com
*/
public class ImagesLoader extends AsyncTaskLoader<>> {
private List mImages = null;
public ImagesLoader(Context context){
super(context);
}
@Override
public List loadInBackground() {
List imageList = new ArrayList();
/**
* 查询本地图片的数据
*/
Cursor imageCursor = getContext().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[]{MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID}, null, null, MediaStore.Images.Media._ID);
if (imageCursor != null && imageCursor.getCount() > 0) {
while (imageCursor.moveToNext()) {
ImageBean item = new ImageBean(imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA)), false);
imageList.add(item);
}
}
if (imageCursor != null) {
imageCursor.close();
}
// show newest photo at beginning of the list
Collections.reverse(imageList);
return imageList;
}
/* Runs on the UI thread */
@Override
public void deliverResult(List images) {
if (isReset()) {
// An async query came in while the loader is stopped
if (images != null) {
images.clear();
images = null;
}
return;
}
List oldImages = mImages;
mImages = images;
if (isStarted()) {
super.deliverResult(images);
}
if (oldImages != null && oldImages != mImages) {
oldImages.clear();
oldImages = null;
}
}
@Override
protected void onStartLoading() {
if (mImages != null && mImages.size() > 0) {
deliverResult(mImages);
}
if (takeContentChanged() || mImages == null) {
forceLoad();
}
}
/**
* Must be called from the UI thread
*/
@Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
@Override
public void onCanceled(List images) {
if (images != null) {
images.clear();
images = null;
}
}
@Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
if (mImages != null) {
mImages.clear();
mImages = null;
}
}
}
考虑到以后保存有图片相关信息的ImageBean可以方便的传递,于是让其实现了Parcelable接口。
实现Parcelable接口的注意事项已经写在代码中,已经很详细了,相信大家能看懂
package com.crazy.wang.model;
import android.os.Parcel;
import android.os.Parcelable;
/**
* @author Cloudsoar(wangyb)
* @datetime 2015-11-30 21:29 GMT+8
* @email 395044952@qq.com
*/
public class ImageBean implements Parcelable {
private String mPath;
private boolean isSelected;
public ImageBean(String path, boolean isSelected){
this.mPath = path;
this.isSelected = isSelected;
}
/**
*
* @return 内容描述,返回0即可
*/
@Override
public int describeContents() {
return 0;
}
/**
* 需要传递的数据都需要通过该方法将数据放入Parcel对象中
* 变量放入的顺序必须是变量声明的顺序,否则会报错
* @param dest
* @param flags
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mPath);
dest.writeInt(isSelected ? 1 : 0);
}
/**
* 实现Parcelable接口的bean必须实例化一个Creator对象,且对象名必须是CREATOR
*/
public static final Creator CREATOR = new Creator() {
/**
* 从Parcel对象中取出数据组装成bean
* 这里的数据来自于writeToParcel方法
* 读取数据时必须是按变量声明的顺序
* @param source
* @return
*/
@Override
public ImageBean createFromParcel(Parcel source) {
return new ImageBean(source.readString(),
source.readInt() == 1 ? true : false);
}
/**
* 返回数组bean
* @param size
* @return
*/
@Override
public ImageBean[] newArray(int size) {
return new ImageBean[size];
}
};
public String getPath() {
return mPath;
}
public void setPath(String path) {
mPath = path;
}
public boolean isSelected() {
return isSelected;
}
public void setIsSelected(boolean isSelected) {
this.isSelected = isSelected;
}
}
在Adapter中,展示图片的时候,使用到了ImageLoader组件