目录
- 基本介绍
- 整体的设计和实现流程
- 资源文件夹的加载和展示
- 主页图片墙的实现
- 预览界面的实现
- 总结
一、基本介绍
Matisse 是「知乎」开源的一款十分精美的本地图像和视频选择库。
Matisse 的代码写的相当的简洁、规范,很有学习的价值。
讲一下 Matisse 的一些优点:
-
在 Activity 或 Fragment 都可以轻松的调用
-
支持各种格式的图片和视频加载
-
支持不同的样式,包括两种内置主题和自定义主题
-
可以自定义文件的过滤规则
可以看到 Matisse 的可拓展性是非常强的,不仅可以自定义我们需要的主题,而且还可以按照需求来过滤出我们想要的文件,除此之外,Matisse 采用了建造者模式,使得我们可以通过链式调用的方式,配置各种各样的属性,使我们的图片选择更加灵活。
二、整体的设计和实现流程
在介绍 Matisse 的工作流程之前,我们先来看看几个比较重要的类,有助于我们后面的理解
类名 | 功能 |
---|---|
Matisse | 通过外部传入的 Activity 或 Fragment,以弱引用的形式进行保存,同时通过 from() 方法返回 SelectionCreator 进行各个参数的配置 |
SelectionCreator | 通过建造者模式,链式配置我们需要的各种属性 |
MatisseActivity | Matisse 首页的 Activity,将图片和视频进行展示 |
我们先从 Matisse 的使用入手,看看 Matisse 的工作流程。
Matisse.from(MainActivity.this)
.choose(MimeType.allOf()) // 1、获取 SelectionCreator
.countable(true)
.maxSelectable(9)
.addFilter(new GifSizeFilter(320, 320, 5 * Filter.K * Filter.K))
.gridExpectedSize(getResources().getDimensionPixelSize(R.dimen.grid_expected_size))
.restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
.thumbnailScale(0.85f)
.imageEngine(new GlideEngine()) // 2、配置各种各样的参数
.forResult(REQUEST_CODE_CHOOSE); // 3、打开 MatisseActivity
上面的使用代码,我们以 Activity 为例,可以分成三部分来看
-
将外部传入的 Activity 以弱引用的形式进行保存,然后调用 choose() 获取 SelectionCreator
-
通过链式调用的方式,配置 SelectionCreator 的各种属性,如可选择的数量、缩略图的大小、加载图片的引擎等
-
使用从第一步中传入的 Activity 调用 startActivityForResult(),并从外部传入请求码,以便到时候返回所选择图片的 List
具体的流程图如下:
以上便是 Matisse 的工作流程,接下来详细的分析下相关的类。有一点要先说明一下,我下面贴出的所有类中的源码并不是完整的代码,而是将源码中与性能、兼容性、扩展性有关的代码剔除后的「核心代码」。
Matisse
public final class Matisse {
private final WeakReference<Activity> mContext;
private final WeakReference<Fragment> mFragment;
private Matisse(Activity activity, Fragment fragment) {
mContext = new WeakReference<>(activity);
mFragment = new WeakReference<>(fragment);
}
public static Matisse from(Activity activity) {
return new Matisse(activity);
}
public static Matisse from(Fragment fragment) {
return new Matisse(fragment);
}
/**
* 在打开 MatisseActivity 的 Activity 或 Fragment 中获取用户选择的媒体 Uri 列表
*/
public static List<Uri> obtainResult(Intent data) {
return data.getParcelableArrayListExtra(MatisseActivity.EXTRA_RESULT_SELECTION);
}
public SelectionCreator choose(Set<MimeType> mimeTypes, boolean mediaTypeExclusive) {
return new SelectionCreator(this, mimeTypes, mediaTypeExclusive);
}
}
这个类的代码还是很简单的,将外部传入的 Activity 或 Fragment,用弱引用的形式保存,防止内存泄露。然后通过 choose() 方法返回 SelectionCreator 用于之后参数的配置。等到图片选择完成后,我们可以在 Fragment 或 Activity 中的 onActivityResult() 中通过 obtainResult() 获取我们所选择媒体的 Uri 列表。
SelectionCreator
public final class SelectionCreator {
private final Matisse mMatisse;
private final SelectionSpec mSelectionSpec;
SelectionCreator(Matisse matisse, @NonNull Set<MimeType> mimeTypes) {
mMatisse = matisse;
mSelectionSpec = SelectionSpec.getCleanInstance();
mSelectionSpec.mimeTypeSet = mimeTypes;
}
public SelectionCreator theme(@StyleRes int themeId) {
mSelectionSpec.themeId = themeId;
return this;
}
public SelectionCreator maxSelectable(int maxSelectable) {
mSelectionSpec.maxSelectable = maxSelectable;
return this;
}
// 其余方法都类似上面这两个,这里面就不贴出来了
public void forResult(int requestCode) {
Activity activity = mMatisse.getActivity();
Intent intent = new Intent(activity, MatisseActivity