How to list all files inside a directory including sub-directories efficiently?

断了今生、忘了曾经 提交于 2019-12-20 05:45:08

问题


I'm working on a gallery app which displays all the images in a phone or a pen-drive. I successfully managed to list all the images and displays it into the app. But I think it is pretty slow. I'm using Depth First Search technique inside an AsyncTask. So is there any other method which can be used inside AsyncTask which is much faster. Here root is a DocumentFile which is made from a tree URI.

Here is the code I've used.

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

}

Here is the output.

Checkout the GIF


回答1:


Do not use DocumentFile.listFiles() to list the files for a tree uri you obtained with Intent.ACTION_OPEN_DOCUMENT_TREE.

As it is notoriously slow.

Instead use functions from DocumentsContract.

Look at the void traverseDirectoryEntries(Uri rootUri) function from Issues traversing through directory hierarchy with Android Storage Access Framework / DocumentProvider using MTP

Collect the child uri for every file instead of trying to obtain a DocumentFile for it.

Then later you can use that child uri to load the image.

If you need six seconds now then it will be less than a second with DocumentsContract i think.




回答2:


This is how I usually do these kinds of things:

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


来源:https://stackoverflow.com/questions/47366768/how-to-list-all-files-inside-a-directory-including-sub-directories-efficiently

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!