【问题标题】:How to list all files inside a directory including sub-directories efficiently?如何有效地列出目录中的所有文件,包括子目录?
【发布时间】:2018-05-02 04:22:05
【问题描述】:

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

这是我使用的代码。

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);

}

这是输出。

Checkout the GIF

【问题讨论】:

  • I'm using DFS 什么是 DFS?
  • for(DocumentFile f:root.listFiles()){ 什么是“根”?
  • DFS :Depth First Search root : 是根目录路径。
  • 那么你不应该告诉你如何获得'root'以及它包含什么吗?您可能同时知道,您的帖子很不清楚。
  • 上传了完整的代码和更多关于root的信息。

标签: android file-io android-asynctask gallery image-gallery


【解决方案1】:

不要使用DocumentFile.listFiles() 列出您使用Intent.ACTION_OPEN_DOCUMENT_TREE 获得的树 uri 的文件。

因为它是出了名的慢。

改用DocumentsContract中的函数。

Issues traversing through directory hierarchy with Android Storage Access Framework / DocumentProvider using MTPvoid traverseDirectoryEntries(Uri rootUri)函数

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

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

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

【讨论】:

  • 圣钼!!!!伙计,这太棒了。就像闪电一样快。不敢相信它会在一秒钟内加载。一个大大的赞。谢谢你,兄弟。真的很感激。
【解决方案2】:

这就是我通常做这些事情的方式:

public ArrayList<String> getFile(File directory) {
File listFile[] = directory.listFiles();
if (listFile != null && listFile.length > 0) {
    for (File file : listFile) {
        if (file.isDirectory()) {
            getFile(file);
        }
        else {
            if (file.getName().endsWith(".png")
                    || file.getName().endsWith(".jpg"))
            {
                String temp = file.getPath().substring(0, file.getPath().lastIndexOf('/'));
                if (!fileList.contains(temp))
                    fileList.add(temp);
            }
        }
    }
}
return fileList;
}

【讨论】:

  • 我之前使用过这种方法,但因为它是一种递归方法,比我的解决方案更快,但它不能在 AsyncTask 中使用。
  • 是的,你是对的......只需在你的doInBackground 方法中调用这个方法......我想就可以了。
  • 当然它也可以在 AsyncTask 中工作。但这是一个无意义的答案,因为它使用 File 类。你的问题是关于 DocumentFile 类的。
  • 他只需使用fromFile(File file)方法就可以轻松地将每个文件更改为DocumentFile。
  • 我认为这是一个逻辑问题。此递归方法也适用于 DocumentFile。我只想在doInBackground 方法中运行,但我们知道这是不可能的。
猜你喜欢
  • 2011-11-09
  • 1970-01-01
  • 1970-01-01
  • 2014-03-08
  • 2023-01-04
  • 2011-08-05
  • 1970-01-01
  • 1970-01-01
  • 2012-11-14
相关资源
最近更新 更多