代码之家  ›  专栏  ›  技术社区  ›  Vivek Patel

如何有效地列出一个目录(包括子目录)中的所有文件?

  •  2
  • Vivek Patel  · 技术社区  · 7 年前

    我正在开发一个画廊应用程序,它可以显示手机或笔驱动器中的所有图像。我成功地列出了所有的图片并将其显示在应用程序中。但我认为这相当慢。我正在使用 Depth First Search 内部技术 AsyncTask . 那么,还有其他方法可以在内部使用吗 异步任务 这要快得多。 在这里,root是一个文档文件,由树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

    2 回复  |  直到 7 年前
        1
  •  7
  •   greenapps    7 年前

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

    因为它是出了名的慢。

    而是使用来自的函数 DocumentsContract .

    看看 void traverseDirectoryEntries(Uri rootUri) 函数来自 Issues traversing through directory hierarchy with Android Storage Access Framework / DocumentProvider using MTP

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

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

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

        2
  •  -1
  •   Mohammad Zarei    7 年前

    我通常是这样做的:

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