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

2023-12-24 12:18

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

本篇博客一起来看Matisse的数据加载机制。

一、AlbumLoader

Matisse采用Loader机制进行加载,先来看AlbumLoader。AlbumLoader集成自CursorLoader,作为资源加载器,加载好资源之后,通过AlbumCollection实现的LoaderManager.LoaderCallbacks接口,将包含数据的Cursor回调给外部调用的MatissActivity。

Loader机制是一种异步加载数据的方式,同常常使用的Handler + Thread方式或者AsyncTask方式一样,被用作数据的异步加载。

相比较于Handler + Thread或者AsyncTask来讲,Loader的封装程度更高,使用起来更简洁,但是灵活性上相比前两者就显得不够灵活。

下面这段代码,通过定义不同的约束,返回了AlbumAdapter实例,Java多态的体现。

public static CursorLoader newInstance(Context context) {String selection;String[] selectionArgs;if (SelectionSpec.getInstance().onlyShowGif()) {selection = beforeAndroidTen()? SELECTION_FOR_SINGLE_MEDIA_GIF_TYPE : SELECTION_FOR_SINGLE_MEDIA_GIF_TYPE_29;selectionArgs = getSelectionArgsForSingleMediaGifType(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE);} else if (SelectionSpec.getInstance().onlyShowImages()) {selection = beforeAndroidTen()? SELECTION_FOR_SINGLE_MEDIA_TYPE : SELECTION_FOR_SINGLE_MEDIA_TYPE_29;selectionArgs = getSelectionArgsForSingleMediaType(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE);} else if (SelectionSpec.getInstance().onlyShowVideos()) {selection = beforeAndroidTen()? SELECTION_FOR_SINGLE_MEDIA_TYPE : SELECTION_FOR_SINGLE_MEDIA_TYPE_29;selectionArgs = getSelectionArgsForSingleMediaType(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO);} else {selection = beforeAndroidTen() ? SELECTION : SELECTION_29;selectionArgs = SELECTION_ARGS;}return new AlbumLoader(context, selection, selectionArgs);}

然后在loadInBackgroud方法中,进行数据的查询

@Overridepublic Cursor loadInBackground() {Cursor albums = super.loadInBackground();MatrixCursor allAlbum = new MatrixCursor(COLUMNS);if (beforeAndroidTen()) {int totalCount = 0;Uri allAlbumCoverUri = null;MatrixCursor otherAlbums = new MatrixCursor(COLUMNS);if (albums != null) {while (albums.moveToNext()) {long fileId = albums.getLong(albums.getColumnIndex(MediaStore.Files.FileColumns._ID));long bucketId = albums.getLong(albums.getColumnIndex(COLUMN_BUCKET_ID));String bucketDisplayName = albums.getString(albums.getColumnIndex(COLUMN_BUCKET_DISPLAY_NAME));String mimeType = albums.getString(albums.getColumnIndex(MediaStore.MediaColumns.MIME_TYPE));Uri uri = getUri(albums);int count = albums.getInt(albums.getColumnIndex(COLUMN_COUNT));otherAlbums.addRow(new String[]{Long.toString(fileId),Long.toString(bucketId), bucketDisplayName, mimeType, uri.toString(),String.valueOf(count)});totalCount += count;}if (albums.moveToFirst()) {allAlbumCoverUri = getUri(albums);}}allAlbum.addRow(new String[]{Album.ALBUM_ID_ALL, Album.ALBUM_ID_ALL, Album.ALBUM_NAME_ALL, null,allAlbumCoverUri == null ? null : allAlbumCoverUri.toString(),String.valueOf(totalCount)});return new MergeCursor(new Cursor[]{allAlbum, otherAlbums});} else {int totalCount = 0;Uri allAlbumCoverUri = null;// Pseudo GROUP BYMap<Long, Long> countMap = new HashMap<>();if (albums != null) {while (albums.moveToNext()) {long bucketId = albums.getLong(albums.getColumnIndex(COLUMN_BUCKET_ID));Long count = countMap.get(bucketId);if (count == null) {count = 1L;} else {count++;}countMap.put(bucketId, count);}}MatrixCursor otherAlbums = new MatrixCursor(COLUMNS);if (albums != null) {if (albums.moveToFirst()) {allAlbumCoverUri = getUri(albums);Set<Long> done = new HashSet<>();do {long bucketId = albums.getLong(albums.getColumnIndex(COLUMN_BUCKET_ID));if (done.contains(bucketId)) {continue;}long fileId = albums.getLong(albums.getColumnIndex(MediaStore.Files.FileColumns._ID));String bucketDisplayName = albums.getString(albums.getColumnIndex(COLUMN_BUCKET_DISPLAY_NAME));String mimeType = albums.getString(albums.getColumnIndex(MediaStore.MediaColumns.MIME_TYPE));Uri uri = getUri(albums);long count = countMap.get(bucketId);otherAlbums.addRow(new String[]{Long.toString(fileId),Long.toString(bucketId),bucketDisplayName,mimeType,uri.toString(),String.valueOf(count)});done.add(bucketId);totalCount += count;} while (albums.moveToNext());}}allAlbum.addRow(new String[]{Album.ALBUM_ID_ALL,Album.ALBUM_ID_ALL, Album.ALBUM_NAME_ALL, null,allAlbumCoverUri == null ? null : allAlbumCoverUri.toString(),String.valueOf(totalCount)});return new MergeCursor(new Cursor[]{allAlbum, otherAlbums});}}

二、AlbumCollection

AlbumCollection是作为AlbumLoader和MatisseActivity的中间层,实现了LoadManager.LoaderCallbacks接口,并通过自定义的AlbumCallbacks,将带数据的Cursor回调给MatisseActivity。

public interface AlbumCallbacks {void onAlbumLoad(Cursor cursor);void onAlbumReset();}

在onCreateLoader里创建了AlbumLoader的实例

@Overridepublic Loader<Cursor> onCreateLoader(int id, Bundle args) {Context context = mContext.get();if (context == null) {return null;}mLoadFinished = false;return AlbumLoader.newInstance(context);}

在onLoadFinished里进行接口的回调

@Overridepublic void onLoadFinished(Loader<Cursor> loader, Cursor data) {Context context = mContext.get();if (context == null) {return;}if (!mLoadFinished) {mLoadFinished = true;mCallbacks.onAlbumLoad(data);}}

同时也使用了onSaveInstanceState与onRestoreInstanceState进行状态的保存与恢复。

通过AlbumCollection这一层的封装,是的MatisseActivity里的代码更加简洁。

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



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

相关文章

Python进阶之Excel基本操作介绍

《Python进阶之Excel基本操作介绍》在现实中,很多工作都需要与数据打交道,Excel作为常用的数据处理工具,一直备受人们的青睐,本文主要为大家介绍了一些Python中Excel的基本操作,希望... 目录概述写入使用 xlwt使用 XlsxWriter读取修改概述在现实中,很多工作都需要与数据打交

使用Python实现批量访问URL并解析XML响应功能

《使用Python实现批量访问URL并解析XML响应功能》在现代Web开发和数据抓取中,批量访问URL并解析响应内容是一个常见的需求,本文将详细介绍如何使用Python实现批量访问URL并解析XML响... 目录引言1. 背景与需求2. 工具方法实现2.1 单URL访问与解析代码实现代码说明2.2 示例调用

SSID究竟是什么? WiFi网络名称及工作方式解析

《SSID究竟是什么?WiFi网络名称及工作方式解析》SID可以看作是无线网络的名称,类似于有线网络中的网络名称或者路由器的名称,在无线网络中,设备通过SSID来识别和连接到特定的无线网络... 当提到 Wi-Fi 网络时,就避不开「SSID」这个术语。简单来说,SSID 就是 Wi-Fi 网络的名称。比如

SpringCloud配置动态更新原理解析

《SpringCloud配置动态更新原理解析》在微服务架构的浩瀚星海中,服务配置的动态更新如同魔法一般,能够让应用在不重启的情况下,实时响应配置的变更,SpringCloud作为微服务架构中的佼佼者,... 目录一、SpringBoot、Cloud配置的读取二、SpringCloud配置动态刷新三、更新@R

使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)

《使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)》在现代软件开发中,处理JSON数据是一项非常常见的任务,无论是从API接口获取数据,还是将数据存储为JSON格式,解析... 目录1. 背景介绍1.1 jsON简介1.2 实际案例2. 准备工作2.1 环境搭建2.1.1 添加

Java汇编源码如何查看环境搭建

《Java汇编源码如何查看环境搭建》:本文主要介绍如何在IntelliJIDEA开发环境中搭建字节码和汇编环境,以便更好地进行代码调优和JVM学习,首先,介绍了如何配置IntelliJIDEA以方... 目录一、简介二、在IDEA开发环境中搭建汇编环境2.1 在IDEA中搭建字节码查看环境2.1.1 搭建步

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

在C#中合并和解析相对路径方式

《在C#中合并和解析相对路径方式》Path类提供了几个用于操作文件路径的静态方法,其中包括Combine方法和GetFullPath方法,Combine方法将两个路径合并在一起,但不会解析包含相对元素... 目录C#合并和解析相对路径System.IO.Path类幸运的是总结C#合并和解析相对路径对于 C

Java解析JSON的六种方案

《Java解析JSON的六种方案》这篇文章介绍了6种JSON解析方案,包括Jackson、Gson、FastJSON、JsonPath、、手动解析,分别阐述了它们的功能特点、代码示例、高级功能、优缺点... 目录前言1. 使用 Jackson:业界标配功能特点代码示例高级功能优缺点2. 使用 Gson:轻量

Java如何接收并解析HL7协议数据

《Java如何接收并解析HL7协议数据》文章主要介绍了HL7协议及其在医疗行业中的应用,详细描述了如何配置环境、接收和解析数据,以及与前端进行交互的实现方法,文章还分享了使用7Edit工具进行调试的经... 目录一、前言二、正文1、环境配置2、数据接收:HL7Monitor3、数据解析:HL7Busines