标签:
知乎的Android开源图片选择框架Matisse源码解析
Matisse中主要的模块有Matisse、SelectionCreator、SelectionSpec、MatisseActivity四个类,它们的工作流程如图:
我们先看到Matisse的使用代码,通过使用的代码来解析源码
Matisse.from(MainActivity.this)
.choose(MimeType.allOf())
.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)// 缩略图的缩放尺寸,默认为0.5
.imageEngine(new GlideEngine())// 图片加载库
.forResult(REQUEST_CODE_CHOOSE);// 启动选择图片Activity
Matisse类
我们从使用时的入口,Matisse类看起。我们进入Matisse的源码,可以看到下面这一部分:
public final class Matisse {
private final WeakReference mContext;
private final WeakReference mFragment;
public static Matisse from(Activity activity) {
return new Matisse(activity);
}
public static Matisse from(Fragment fragment) {
return new Matisse(fragment);
}
...
@Nullable
Activity getActivity() {
return (Activity)this.mContext.get();
}
public SelectionCreator choose(Set mimeTypes) {
return this.choose(mimeTypes, true);
}
public SelectionCreator choose(Set mimeTypes, boolean mediaTypeExclusive) {
return new SelectionCreator(this, mimeTypes, mediaTypeExclusive);
}
@Nullable
Fragment getFragment() {
return this.mFragment != null ? (Fragment)this.mFragment.get() : null;
}
}
我们可以发现,Matisse中用弱引用保存了Activity及Fragment的引用。它的from方法有两个重载,一个是传入Activity,一个是传入Fragment。也就是它同时支持了Activity及Fragment。它的choose方法有两个重载,最后都创建了一个SelectionCreator类。
SelectionCreator类-配置部分
我们看到SelectionCreator类的源码
public final class SelectionCreator {
private final Matisse mMatisse;
private final SelectionSpec mSelectionSpec;
SelectionCreator(Matisse matisse, @NonNull Set mimeTypes,
boolean mediaTypeExclusive){
this.mMatisse = matisse;
this.mSelectionSpec = SelectionSpec.getCleanInstance();
this.mSelectionSpec.mimeTypeSet = mimeTypes;
this.mSelectionSpec.mediaTypeExclusive = mediaTypeExclusive;
this.mSelectionSpec.orientation = -1;
}
public SelectionCreator countable(boolean countable) {
mSelectionSpec.countable = countable;
return this;
}
public SelectionCreator maxSelectable(int maxSelectable) {
if (maxSelectable < 1)
throw new IllegalArgumentException("maxSelectable must be greater than or equal to one");
mSelectionSpec.maxSelectable = maxSelectable;
return this;
}
...
}
可以看到,它内部保存了刚刚创建的Matisse及一个SelectionSpec类。SelectionCreator类采用了一种Builder的设计,比较巧妙的是将它的配置属性都放到了SelectionSpec类中。
SelectionSpec类
我们可以查看SelectionSpec的源码
public final class SelectionSpec {
public Set mimeTypeSet;
public boolean mediaTypeExclusive;
... //一些配置属性
private SelectionSpec() {
}
public static SelectionSpec getInstance() {
return SelectionSpec.InstanceHolder.INSTANCE;
}
public static SelectionSpec getCleanInstance() {
SelectionSpec