这个Demo类似Android的图库一样能扫描手机目录的大部分的图片,查看,管理,操作图片。这个Demo的组成是以MVP作为App的主要框架, Rxjava, Dagger作为辅助工具。
App的展示:
需要说明一下,我这个Album Demo只是我这个AllDemo
的一个子Demo,里面还包括了几个Demo的。而整个AllDemo也是采用MVP框架的。
首先来说下ImageLoader和一些功能类。
这个类主要用来加载手机内的绝大部分图片,这不包括全部,原因有些其他App的图片是私有的。
loadDeviceImages方法用来加载手机图片,并返回Observable对象,这是RxJava的一个对象。想了解更多RxJava可以到官方wiki查看,毕竟我还没到熟悉程度,还在学习当中。
/**
* load device images
* @return Observable>
*/
private Observable> loadDeviceImages() {
return new Observable>() {
@Override
protected void subscribeActual(Observer super List> observer) {
Cursor cursor = mContext.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
columnIndexs, null, null, MediaStore.Images.Media.DATE_ADDED);
if (cursor == null) {
observer.onError(new NullPointerException());
}
// save all Image temporary
List temp = new ArrayList<>(cursor.getCount());
// 用于缓存加载的图片
mCacheDirty = true;
if (mCacheFolders == null) {
mCacheFolders = new LinkedHashMap<>();
}
if (cursor.moveToLast()) {
do {
long id = cursor.getLong(cursor.getColumnIndex(columnIndexs[0]));
String name = cursor.getString(cursor.getColumnIndex(columnIndexs[1]));
String path = cursor.getString(cursor.getColumnIndex(columnIndexs[2]));
String bucket = cursor.getString(cursor.getColumnIndex(columnIndexs[3]));
File file = new File(path);
if (file.exists()) {
Image image = new Image(id, name, path, false);
temp.add(image);
Folder folder = mCacheFolders.get(bucket);
if (folder == null) {
folder = new Folder(bucket);
mCacheFolders.put(bucket, folder);
}
folder.getImages().add(image);
}
} while (cursor.moveToPrevious());
}
cursor.close();
List folders = new ArrayList<>(mCacheFolders.values());
observer.onNext(folders);
}
};
}
该方法用到的是Observable.concat的操作方法,该方法用了两个参数方法,’loadCacheImages()’和’loadDeviceImages()’
而concat首先判断前一个是否返回null,如果返回null,再取第二个’loadDeviceImages()’返回值,如果又是null,
则取first,初始化List。然而,这样可以做到缓存的作用。
public Single> loadImages() {
return Observable.concat(loadCacheImages(), loadDeviceImages())
.first(new ArrayList());
}
public interface CameraModule {
Intent getCameraIntent(Context context);
void getImage(Context context, Intent intent, ImageCaptureReadyListener listener);
}
CameraModule是一个接口。’getCameraIntent()’返回调用相机的一个intent, ‘getImage()’在调用
相机,拍照完照片后,在Activity的’onActivityResult()’方法调用,把拍照完的照片文件加入到media content里面。
如果不这么做,在调用'loadDeviceImages()'时,执行下面代码时获取不了那张图片的。所以需要注意。
Cursor cursor = mContext.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
columnIndexs, null, null, MediaStore.Images.Media.DATE_ADDED);
DefaultCameraModule是CameraModule接口的实现类。
ImageCaptureReadyListener是一个监听接口,在调用CameraModule的’getImage()’方法时,在scanFile
完成后调用。
下面要讲下这个Album Demo的MVP框架
AlbumContract类是定义了V和P的方法,所有关于UI显示都写在这个V上,所有有关逻辑方面的都写在这个P上。
M就是我们数据的Model,比如这里的Image, Folder类。其实可以通过AlbumContract类的一些方法可以看出,
这个Demo所具有的一些功能表面,这也是MVP的好处,功能清晰,分明。如果对于整个项目来说,每一个功能及UI最好
写到一个包里面。
它们之间的关系如下图:
这里忘记要说的是,这个Demo只用了一个MainActivity,所有的界面都是用了Fragment。当然每个Fragment
都继承了一个基类的,基类都在base包。
希望大家可以看下AlbumFragment和AlbumPresenter对Contract的方法的实现。
下面就是要讲下用到的Dagger注入工具
AlbumModule和AlbumComponent是Dagger需要的类,具体还是看看官方文档。
Dagger比如要做一道菜,Module是所需要的配料,和材料,Compoenent犹如把各个配料和材料搞在一起或装在一起,
待放入锅里或煲里。对于Dagger自己还没有深入的了解,所以也是在实践和研究当中。因此这块暂时不多说,上来
先看代码,主要看怎么用先。等我有了深入了解,再来分享下囖。
这个AllDemo项目还在不断完善当中,里面有些UI,工具类,也有参考了他人的代码,自己也是新人吧,希望各路
大神可以给下建议和修改。毕竟自己写的代码还不是很优雅的,还要继续的提升。