如何有效地列出目录中的所有文件,包括子目录?
How to list all files inside a directory including sub-directories efficiently?
我正在开发一个图库应用程序,它可以在 phone 或笔式驱动器中显示所有图像。我成功地列出了所有图像并将其显示到应用程序中。但我认为这很慢。我在 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
这就是我通常做这些事情的方式:
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;
}
不要使用 DocumentFile.listFiles()
列出您使用 Intent.ACTION_OPEN_DOCUMENT_TREE
获得的树 uri 的文件。
因为它是出了名的慢。
改为使用 DocumentsContract
.
中的函数
查看
中的void traverseDirectoryEntries(Uri rootUri)
函数
收集每个文件的子 uri,而不是尝试为其获取 DocumentFile。
然后您可以使用该子 uri 来加载图像。
如果您现在需要六秒,那么我认为使用 DocumentsContract 将不到一秒。
我正在开发一个图库应用程序,它可以在 phone 或笔式驱动器中显示所有图像。我成功地列出了所有图像并将其显示到应用程序中。但我认为这很慢。我在 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
这就是我通常做这些事情的方式:
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;
}
不要使用 DocumentFile.listFiles()
列出您使用 Intent.ACTION_OPEN_DOCUMENT_TREE
获得的树 uri 的文件。
因为它是出了名的慢。
改为使用 DocumentsContract
.
查看
void traverseDirectoryEntries(Uri rootUri)
函数
收集每个文件的子 uri,而不是尝试为其获取 DocumentFile。
然后您可以使用该子 uri 来加载图像。
如果您现在需要六秒,那么我认为使用 DocumentsContract 将不到一秒。