Android 11:DocumentFile findFile() 太慢
Android 11: DocumentFile findFile() is too slow
随着 Google 存储策略的更新,我不得不改变我保存文件的方式。
首先,我的应用程序之前将项目文件夹保存到/sdcard/。但是,由于这个政策,无法使用文件访问,我尝试了几种方法。
我也想过把它保存在一个App专用文件里space,但是由于删除app时项目文件夹不能被删除,所以不能用
1.使用 MediaStore
起初,我尝试使用 MediaStore。
我可以使用RELATIVE_PATH将文件放在一个文件夹中,但是文件的控制非常困难,而且项目文件夹中的文件也是与媒体(照片,视频,音乐)无关的文件.
2。使用文档文件
我找到了另一种方法。使用 Intent 的 ACTION_OPEN_DOCUMENT_TREE,我从用户那里获得了项目文件夹的访问权限和树 uri,并且我能够通过使用它创建一个 DocumentFile 来访问该文件。
起初我认为这是一个很好的方法,但很快我发现它很慢。
特别是findFile()方法,扫描单个文件需要将近一秒的时间。
我的项目文件夹中有几十个文件,所以不能商业化。
有没有更好的方法?
已经有一些帖子要求您试用 DocumentContracts,但似乎没有获取文件列表或检查它们是否存在的功能。
下面是我当前的代码:
首先,请求树uri:
public void getTreeUri(View view) {
Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(i, 200);
}
其次,获取树uri:
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==200 && resultCode == Activity.RESULT_OK) {
final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().takePersistableUriPermission(data.getData(), takeFlags);
Log.d("test", "Tree Uri: " + data.getDataString());
treeUri = data.getDataString();
getFileList();
}
}
而且,特别是,当像这样使用 findFile 时它变得非常慢。
public void getFileList(){
DocumentFile df = DocumentFile.fromTreeUri(this, Uri.parse(treeUri));
DocumentFile[] df_list = df.listFiles();
for (DocumentFile each : df_list){
Log.d("test","File: "+ df.findFile(each.getName())); //findFile method is too SLOW!
}
}
对于 Android 10,您可以在清单中请求旧的外部存储,然后您可以使用文件 class 等以旧方式继续。
对于 Android 11,在 public 目录之一中使用您自己的目录,例如下载、文档、图片、警报等。也不需要 saf。
SAF确实很慢,findFile()
算法没有优化的时候更慢。根据 my benchmark with extension function DocumentFile.child()
from SimpleStorage,它的执行速度可以提高 36%。
要使用此功能,只需将 findFile()
替换为 child()
:
// Before
val file = folder.findFile("Movies")?.findFile("Infinity War.mp4")
// After
val file = folder.child("Movies/Infinity War.mp4")
随着 Google 存储策略的更新,我不得不改变我保存文件的方式。
首先,我的应用程序之前将项目文件夹保存到/sdcard/。但是,由于这个政策,无法使用文件访问,我尝试了几种方法。
我也想过把它保存在一个App专用文件里space,但是由于删除app时项目文件夹不能被删除,所以不能用
1.使用 MediaStore
起初,我尝试使用 MediaStore。 我可以使用RELATIVE_PATH将文件放在一个文件夹中,但是文件的控制非常困难,而且项目文件夹中的文件也是与媒体(照片,视频,音乐)无关的文件.
2。使用文档文件
我找到了另一种方法。使用 Intent 的 ACTION_OPEN_DOCUMENT_TREE,我从用户那里获得了项目文件夹的访问权限和树 uri,并且我能够通过使用它创建一个 DocumentFile 来访问该文件。
起初我认为这是一个很好的方法,但很快我发现它很慢。
特别是findFile()方法,扫描单个文件需要将近一秒的时间。 我的项目文件夹中有几十个文件,所以不能商业化。
有没有更好的方法? 已经有一些帖子要求您试用 DocumentContracts,但似乎没有获取文件列表或检查它们是否存在的功能。
下面是我当前的代码: 首先,请求树uri:
public void getTreeUri(View view) {
Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(i, 200);
}
其次,获取树uri:
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==200 && resultCode == Activity.RESULT_OK) {
final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().takePersistableUriPermission(data.getData(), takeFlags);
Log.d("test", "Tree Uri: " + data.getDataString());
treeUri = data.getDataString();
getFileList();
}
}
而且,特别是,当像这样使用 findFile 时它变得非常慢。
public void getFileList(){
DocumentFile df = DocumentFile.fromTreeUri(this, Uri.parse(treeUri));
DocumentFile[] df_list = df.listFiles();
for (DocumentFile each : df_list){
Log.d("test","File: "+ df.findFile(each.getName())); //findFile method is too SLOW!
}
}
对于 Android 10,您可以在清单中请求旧的外部存储,然后您可以使用文件 class 等以旧方式继续。
对于 Android 11,在 public 目录之一中使用您自己的目录,例如下载、文档、图片、警报等。也不需要 saf。
SAF确实很慢,findFile()
算法没有优化的时候更慢。根据 my benchmark with extension function DocumentFile.child()
from SimpleStorage,它的执行速度可以提高 36%。
要使用此功能,只需将 findFile()
替换为 child()
:
// Before
val file = folder.findFile("Movies")?.findFile("Infinity War.mp4")
// After
val file = folder.child("Movies/Infinity War.mp4")