如何有效地列出包括子目录在内的目录中的所有文件?

Viv*_*tel 0 file-io android gallery image-gallery android-asynctask

我正在开发一个画廊应用程序,该应用程序显示手机或笔式驱动器中的所有图像。我成功地列出了所有图像并将其显示在应用程序中。但我认为它很慢。我使用的Depth First Search技术内的AsyncTask。那么有没有其他方法可以在里面使用AsyncTask,速度要快得多。这里的 root 是一个由树 URI 组成的 DocumentFile。

这是我使用过的代码。

public class ImageBackgroundTask extends AsyncTask<Object, Object, ArrayList<DocumentFile>> {
DocumentFile root;
ArrayList<DocumentFile> result;
ProgressDialog pg;
Context context;
private AsyncTaskCompleteListener<ArrayList<DocumentFile> > callback;

ImageBackgroundTask(DocumentFile root, Context context, AsyncTaskCompleteListener<ArrayList<DocumentFile>> cb){
    this.context=context;
    this.root=root;
    this.callback = cb;

}
@Override
protected ArrayList<DocumentFile> doInBackground(Object... voids) {
    Queue<DocumentFile> stack=new ArrayDeque<>();
    ArrayList<DocumentFile> list=new ArrayList<>();
    for(DocumentFile f:root.listFiles()){
        stack.add(f);
    }
    while(!stack.isEmpty()){
        DocumentFile child=stack.remove();
        if(child.isDirectory()){
            for(DocumentFile file:child.listFiles()){
                stack.add(file);
            }
        }
        else if(child.isFile()){
            String name=child.getName();
            if(name.endsWith(".jpg")
                    || name.endsWith(".png")
                    || name.endsWith("jpeg")
                    || name.endsWith("JPG")
                    || name.endsWith("JPEG")
                    || name.endsWith("PNG"))
                list.add(child);
        }
    }
    return list;
}

@Override
protected void onPreExecute() {
    pg=new ProgressDialog(context);
    pg.setMessage("Loading...");
    pg.show();

}

@Override
protected void onProgressUpdate(Object... values) {
    super.onProgressUpdate(values);
}

@Override
protected void onPostExecute(ArrayList<DocumentFile> aVoid) {
    pg.dismiss();
    result=aVoid;
    callback.onTaskComplete(result);

}
Run Code Online (Sandbox Code Playgroud)

这是输出。

查看 GIF

gre*_*pps 5

不要DocumentFile.listFiles()用于列出您通过Intent.ACTION_OPEN_DOCUMENT_TREE.

因为它是出了名的慢。

而是使用来自DocumentsContract.

查看使用 MTP 使用 Android Storage Access Framework / DocumentProvider 遍历目录层次结构的问题中的void traverseDirectoryEntries(Uri rootUri)函数

为每个文件收集子 uri,而不是尝试为其获取 DocumentFile。

然后,您可以使用该子 uri 加载图像。

如果您现在需要六秒钟,那么我认为 DocumentsContract 将不到一秒钟。