问题
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