Android进阶 -- 知乎Matisse源码解析(一)

2023-12-24 12:18

本文主要是介绍Android进阶 -- 知乎Matisse源码解析(一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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).imageEngine(new GlideEngine()).showPreview(false) // Default is `true`.forResult(REQUEST_CODE_CHOOSE);

然后在onActivityResult里回调给我们结果

List<Uri> mSelected;@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == REQUEST_CODE_CHOOSE && resultCode == RESULT_OK) {mSelected = Matisse.obtainResult(data);Log.d("Matisse", "mSelected: " + mSelected);}
}

使用起来非常方便,接下来,一起看看它的内部是怎么实现的。

首先,从入口函数看起

public final class Matisse {private final WeakReference<Activity> mContext;private final WeakReference<Fragment> mFragment;private Matisse(Activity activity) {this(activity, null);}private Matisse(Fragment fragment) {this(fragment.getActivity(), fragment);}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);}public static List<Uri> obtainResult(Intent data) {return data.getParcelableArrayListExtra(MatisseActivity.EXTRA_RESULT_SELECTION);}public static List<String> obtainPathResult(Intent data) {return data.getStringArrayListExtra(MatisseActivity.EXTRA_RESULT_SELECTION_PATH);}public static boolean obtainOriginalState(Intent data) {return data.getBooleanExtra(MatisseActivity.EXTRA_RESULT_ORIGINAL_ENABLE, false);}public SelectionCreator choose(Set<MimeType> mimeTypes) {return this.choose(mimeTypes, true);}public SelectionCreator choose(Set<MimeType> mimeTypes, boolean mediaTypeExclusive) {return new SelectionCreator(this, mimeTypes, mediaTypeExclusive);}@NullableActivity getActivity() {return mContext.get();}@NullableFragment getFragment() {return mFragment != null ? mFragment.get() : null;}}

(1)from两个重载函数,分别接收Activity和Fragment实例,从而保证用户可以在Activity和Fragment直接调用,在方法里通过私有构造函数创建了Matisse的实例,并且都为弱引用,由于选择媒体的操作往往都是一步完成,不需要持有强引用的实例,使用弱引用,在下一次GC的时候,可以实现内存空间的回收。

(2)choose函数用来返回SelectionCreator对象实例并且确定选取的媒体类型(可查看源码里的MimeType枚举类),SelectionCreator使用建造者模式,根据用户的具体需求来初始化一些变量,下面举几个栗子,更多的设置可以查看SelectionCreator的源码,里面的注释都很到位。

  • countable:是否开启序号自增计数
  • maxSelectable:最大选择数
  • addFilter:文件过滤,源码定义了抽象类Filter,用户可以根据需求去自定义Filter
  • theme:设置主题
  • imageEngine:图片加载引擎

(3)imageEngine:Matisse支持目前主流的图片加载框架glide和picasso,源码里定义了图片引擎接口IamgeEngine

@SuppressWarnings("unused")
public interface ImageEngine {void loadThumbnail(Context context, int resize, Drawable placeholder, ImageView imageView, Uri uri);void loadGifThumbnail(Context context, int resize, Drawable placeholder, ImageView imageView, Uri uri);void loadImage(Context context, int resizeX, int resizeY, ImageView imageView, Uri uri);void loadGifImage(Context context, int resizeX, int resizeY, ImageView imageView, Uri uri);boolean supportAnimatedGif();
}

然后使用glide和picasso分别实现了ImageEngine,对应的源码是GlideEngine和PicassoEngine,如果项目里使用的Glide或者Picasso直接使用就好,如果使用fresco或者其他ImageLoader,只需要实现ImageEngine接口,在将其传递进去就好,这里也体现出了一个良好的开源框架的可拓展性。

(4)SelectionCreator内部持有了Matisse的SelectionSpec的实例,Matisse在启动Activity或者Fragment的时候会用到,而SelectionSpec则是所有设置变量的实体类,前面设置的属性都保存在SelectionSpec实体类里,SelectionSpec采用了非线程安全的单例模式写法,因为这里并没有线程安全的隐患,这样写销量更高。

(5)forResult方法启动了MatisseActivity,这个Activity也就是我们看到的图片选择Activity,并且设置了onActivityResult的回调

public void forResult(int requestCode) {Activity activity = mMatisse.getActivity();if (activity == null) {return;}Intent intent = new Intent(activity, MatisseActivity.class);Fragment fragment = mMatisse.getFragment();if (fragment != null) {fragment.startActivityForResult(intent, requestCode);} else {activity.startActivityForResult(intent, requestCode);}}

本篇文章为Matisse源码解读系列的第一篇,了解了Matisse的用法和相关配置的源码部分,下一篇将开始看启动MatisseActivity之后的源码实现。

这篇关于Android进阶 -- 知乎Matisse源码解析(一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/531743

相关文章

Android DataBinding 与 MVVM使用详解

《AndroidDataBinding与MVVM使用详解》本文介绍AndroidDataBinding库,其通过绑定UI组件与数据源实现自动更新,支持双向绑定和逻辑运算,减少模板代码,结合MV... 目录一、DataBinding 核心概念二、配置与基础使用1. 启用 DataBinding 2. 基础布局

Android ViewBinding使用流程

《AndroidViewBinding使用流程》AndroidViewBinding是Jetpack组件,替代findViewById,提供类型安全、空安全和编译时检查,代码简洁且性能优化,相比Da... 目录一、核心概念二、ViewBinding优点三、使用流程1. 启用 ViewBinding (模块级

Spring Boot 实现 IP 限流的原理、实践与利弊解析

《SpringBoot实现IP限流的原理、实践与利弊解析》在SpringBoot中实现IP限流是一种简单而有效的方式来保障系统的稳定性和可用性,本文给大家介绍SpringBoot实现IP限... 目录一、引言二、IP 限流原理2.1 令牌桶算法2.2 漏桶算法三、使用场景3.1 防止恶意攻击3.2 控制资源

Java Spring ApplicationEvent 代码示例解析

《JavaSpringApplicationEvent代码示例解析》本文解析了Spring事件机制,涵盖核心概念(发布-订阅/观察者模式)、代码实现(事件定义、发布、监听)及高级应用(异步处理、... 目录一、Spring 事件机制核心概念1. 事件驱动架构模型2. 核心组件二、代码示例解析1. 事件定义

CSS place-items: center解析与用法详解

《CSSplace-items:center解析与用法详解》place-items:center;是一个强大的CSS简写属性,用于同时控制网格(Grid)和弹性盒(Flexbox)... place-items: center; 是一个强大的 css 简写属性,用于同时控制 网格(Grid) 和 弹性盒(F

python常见环境管理工具超全解析

《python常见环境管理工具超全解析》在Python开发中,管理多个项目及其依赖项通常是一个挑战,下面:本文主要介绍python常见环境管理工具的相关资料,文中通过代码介绍的非常详细,需要的朋友... 目录1. conda2. pip3. uvuv 工具自动创建和管理环境的特点4. setup.py5.

全面解析HTML5中Checkbox标签

《全面解析HTML5中Checkbox标签》Checkbox是HTML5中非常重要的表单元素之一,通过合理使用其属性和样式自定义方法,可以为用户提供丰富多样的交互体验,这篇文章给大家介绍HTML5中C... 在html5中,Checkbox(复选框)是一种常用的表单元素,允许用户在一组选项中选择多个项目。本

Python包管理工具核心指令uvx举例详细解析

《Python包管理工具核心指令uvx举例详细解析》:本文主要介绍Python包管理工具核心指令uvx的相关资料,uvx是uv工具链中用于临时运行Python命令行工具的高效执行器,依托Rust实... 目录一、uvx 的定位与核心功能二、uvx 的典型应用场景三、uvx 与传统工具对比四、uvx 的技术实

SpringBoot排查和解决JSON解析错误(400 Bad Request)的方法

《SpringBoot排查和解决JSON解析错误(400BadRequest)的方法》在开发SpringBootRESTfulAPI时,客户端与服务端的数据交互通常使用JSON格式,然而,JSON... 目录问题背景1. 问题描述2. 错误分析解决方案1. 手动重新输入jsON2. 使用工具清理JSON3.

从基础到进阶详解Pandas时间数据处理指南

《从基础到进阶详解Pandas时间数据处理指南》Pandas构建了完整的时间数据处理生态,核心由四个基础类构成,Timestamp,DatetimeIndex,Period和Timedelta,下面我... 目录1. 时间数据类型与基础操作1.1 核心时间对象体系1.2 时间数据生成技巧2. 时间索引与数据