点击蓝字关注我们哟~
开发 漫品 客户端 本地图书导入页面 的过程中,需要获取到手机目录中所有的txt文件进行展示用于提供给的用户进行
如果使用Java读取目录,目前想到的是递归的方式进行文件获取,但获取过程其实是比较缓慢的,基于获取到的文件再向下进行传递。如果手机文件较多,内容较多的话,这并不是一个好的选中,
也许查找时间会非常的长。
private void searchBook(ObservableEmitter<File> e, File parentFile) {
if (null != parentFile && parentFile.listFiles() != null &&parentFile.listFiles().length > 0) {
File[] childFiles = parentFile.listFiles();
for (int i = 0; i < childFiles.length; i++) {
if (childFiles[i].isFile() && childFiles[i].getName().substring(childFiles[i].getName().lastIndexOf(".") + 1).equalsIgnoreCase("txt") && childFiles[i].length() > 100 * 1024) { //100kb
e.onNext(childFiles[i]);
continue;
}
if (childFiles[i].isDirectory() && childFiles[i].listFiles().length > 0) {
searchBook(e, childFiles[i]);
}
}
}}
Loader 顾名思义 就是 加载器。
借助 Loader API,您可以从内容提供程序或其他数据源中加载数据,以便在 FragmentActivity 或 Fragment 中显示。如果您不理解为何需要 Loader API 来执行这个看似无关紧要的操作,请首先考虑没有加载器时可能会遇到的一些问题:
加载器不仅能解决这些问题,同时还具备其他优势。例如:
上面是官方的介绍,其实总结下就是以下两点:
在应用中使用加载器时,可能会涉及到多个类和接口。下表对其进行了总结:
一种与 FragmentActivity 或 Fragment 相关联的抽象类,用于管理一个或多个 Loader 实例。每个 Activity 或片段只有一个 LoaderManager,但 LoaderManager 可管理多个加载器。
如要获取 LoaderManager,请从 Activity 或片段调用 getSupportLoaderManager()。
如要从加载器开始加载数据,请调用 initLoader() 或 restartLoader()。系统会自动确定是否已存在拥有相同整型 ID 的加载器,并将创建新加载器或重复使用现有的加载器。
此接口包含加载器事件发生时所调用的回调方法。接口定义三种回调方法:
此接口一般由您的 Activity 或片段实现,并在您调用 initLoader() 或 restartLoader() 时进行注册。
Loader 类执行数据的加载。此类属于抽象类,并且是所有加载器的基类。您可以直接创建 Loader 的子类,或使用以下某个内置子类来简化实现:
使用loader的几个必备条件如下:
/**
* Gets a LoaderManager associated with the given owner, such as a {@link androidx.fragment.app.FragmentActivity} or
* {@link androidx.fragment.app.Fragment}.
*
* @param owner The owner that should be used to create the returned LoaderManager
* @param <T> A class that maintains its own {@link android.arch.lifecycle.Lifecycle} and
* {@link android.arch.lifecycle.ViewModelStore}. For instance,
* {@link androidx.fragment.app.FragmentActivity} or {@link androidx.fragment.app.Fragment}.
* @return A valid LoaderManager
*/@NonNullpublic static <T extends LifecycleOwner & ViewModelStoreOwner> LoaderManager getInstance(
@NonNull T owner) {
return new LoaderManagerImpl(owner, owner.getViewModelStore());}
LoaderManager.LoaderCallbacks<D>接口是LoaderManager用来向客户返回数据的方式。
每个Loader都有自己的回调对象供与LoaderManager进行交互。
该回调对象在实现LoaderManager中地位很高,告诉LoaderManager如何实例化Loader(onCreateLoader),以及当载入行为结束或者重启(onLoadFinished或者onLoadReset)之后执行什么操作。
大多数情况,你需要把该接口实现为组件的一部分,比如说让你的Activity或者Fragment实现
LoadManager.LoaderCallbacks<D>接口。
public interface LoaderCallbacks<D> {
@MainThread
@NonNull
Loader<D> onCreateLoader(int id, @Nullable Bundle args);
@MainThread void onLoadFinished(@NonNull Loader<D> loader, D data);
@MainThread void onLoaderReset(@NonNull Loader<D> loader);}
一旦实现该接口,客户端将回调对象(本例中为“this”)作为LoaderManager的initLoader函数的第三个参数传输。
总的来说,实现回调接口非常直接明了。每个回调方法都有各自明确的与LoaderManager进行交互的目的:
源码地址: https://github.com/AnyMarvel/ManPinAPP
路径 app/src/main/java/com/mp/android/apps/monke/monkeybook/utils/media
package com.mp.android.apps.monke.monkeybook.utils.media;import android.content.Context;import android.database.Cursor;import android.os.Bundle;import androidx.fragment.app.FragmentActivity;import androidx.loader.app.LoaderManager;import androidx.loader.content.Loader;import java.io.File;import java.lang.ref.WeakReference;import java.util.List;/**
* 获取媒体库的数据。
*/public class MediaStoreHelper {
/**
* 获取媒体库中所有的书籍文件
* <p>
* 暂时只支持 TXT
*
* @param activity
* @param resultCallback
*/
public static void getAllBookFile(FragmentActivity activity, MediaResultCallback resultCallback) {
// 将文件的获取处理交给 LoaderManager。
LoaderManager.getInstance(activity)
.initLoader(LoaderCreator.ALL_BOOK_FILE, null, new MediaLoaderCallbacks(activity, resultCallback));
}
public interface MediaResultCallback {
void onResultCallback(List<File> files);
}
/**
* Loader 回调处理
*/
static class MediaLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
protected WeakReference<Context> mContext;
protected MediaResultCallback mResultCallback;
public MediaLoaderCallbacks(Context context, MediaResultCallback resultCallback) {
mContext = new WeakReference<>(context);
mResultCallback = resultCallback;
}
@Override public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return LoaderCreator.create(mContext.get(), id, args);
}
@Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
LocalFileLoader localFileLoader = (LocalFileLoader) loader;
localFileLoader.parseData(data, mResultCallback);
}
@Override public void onLoaderReset(Loader<Cursor> loader) {
}
}}
LoaderCreator.java
package com.mp.android.apps.monke.monkeybook.utils.media;import android.content.Context;import android.os.Bundle;import androidx.loader.content.CursorLoader;public class LoaderCreator {
public static final int ALL_BOOK_FILE = 1;
public static CursorLoader create(Context context, int id, Bundle bundle) {
LocalFileLoader loader = null;
switch (id){
case ALL_BOOK_FILE:
loader = new LocalFileLoader(context);
break;
default:
loader = null;
break;
}
if (loader != null) {
return loader;
}
throw new IllegalArgumentException("The id of Loader is invalid!");
}}
LocalFileLoader.java
package com.mp.android.apps.monke.monkeybook.utils.media;import android.content.Context;import android.database.Cursor;import android.net.Uri;import android.provider.MediaStore;import android.text.TextUtils;import androidx.annotation.NonNull;import androidx.loader.content.CursorLoader;import java.io.File;import java.sql.Blob;import java.util.ArrayList;import java.util.List;public class LocalFileLoader extends CursorLoader {
private static final String TAG = "LocalFileLoader";
private static final Uri FILE_URI = Uri.parse("content://media/external/file");
private static final String SELECTION = MediaStore.Files.FileColumns.DATA + " like ?";
private static final String SEARCH_TYPE = "%.txt";
private static final String SORT_ORDER = MediaStore.Files.FileColumns.DISPLAY_NAME + " DESC";
private static final String[] FILE_PROJECTION = {
MediaStore.Files.FileColumns.DATA,
MediaStore.Files.FileColumns.DISPLAY_NAME };
public LocalFileLoader(Context context) {
super(context);
initLoader();
}
/**
* 为 Cursor 设置默认参数
*/
private void initLoader() {
setUri(FILE_URI);
setProjection(FILE_PROJECTION);
setSelection(SELECTION);
setSelectionArgs(new String[]{SEARCH_TYPE});
setSortOrder(SORT_ORDER);
}
public void parseData(Cursor cursor, final MediaStoreHelper.MediaResultCallback resultCallback) {
List<File> files = new ArrayList<>();
// 判断是否存在数据
if (cursor == null) {
// TODO:当媒体库没有数据的时候,需要做相应的处理
// 暂时直接返回空数据
resultCallback.onResultCallback(files);
return;
}
// 重复使用Loader时,需要重置cursor的position;
cursor.moveToPosition(-1);
while (cursor.moveToNext()) {
String path;
path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA));
// 路径无效
if (TextUtils.isEmpty(path)) {
continue;
} else {
File file = new File(path);
if (file.isDirectory() || !file.exists()){
continue;
}
else {
files.add(file);
}
}
}
if (resultCallback != null) {
resultCallback.onResultCallback(files);
}
}}
以上是漫品 客户端加载本地文件的方式,欢迎有更好方式的童鞋留言。
https://github.com/AnyMarvel/ManPinAPP
欢迎各位大大 start
漫品 客户端小说模块:
阅读页支持:
夯实基础,关注前沿,娱乐生活
掌握更多前沿技术,获取更多笑点
请关注--------喘口仙氣