gpt4 book ai didi

android - 为什么 AssetManger.list() 这么慢?

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:52:34 25 4
gpt4 key购买 nike

我正在尝试使用存储在 SD 卡上并作为 Assets 存储在 APK 中的混合文件来填充 ListView。使用 TraceView,我可以看到 AssetManager.list() 的性能比 File.listFiles() 差,即使我我正在为 SD 卡使用文件名过滤器。

这是一个简单的方法,可以从 SD 卡上的文件夹中返回所有 png 文件:

// The folder on SDcard may contain files other than png, so filter them out
private File[] getMatchingFiles(File path) {
File[] flFiles = path.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
name = name.toLowerCase();
return name.endsWith(".png");
}
});
return flFiles;
}

我在这里调用该方法,检索 16 个文件大约需要 12 毫秒:

final String state = Environment.getExternalStorageState();           
if (Environment.MEDIA_MOUNTED.equals(state)||Environment.MEDIA_SHARED.equals(state)) {
File path = Environment.getExternalStoragePublicDirectory(getResources().getString(R.string.path_dir));
if (path.exists()){
File[] files = getMatchingFiles(path);
...

而 am.list 方法需要 49 毫秒才能检索大约 6 个文件的名称!

// Get all filenames from specific Asset Folder and store them in String array
AssetManager am = getAssets();
String path = getResources().getString(R.string.path_dir);
String[] fileNames = am.list(path);
...

谁能解释为什么性能会这么差?性能是否与 APK 中存储的 Assets 数量成正比?我知道 Assets 是压缩的,但我只是获取 Assets 的名称,我认为这些名称会存储在某个表中。

最佳答案

Coverdriven 的评论“存储在某处的表中”启发了我去解决我自己的问题,这个问题我已经推迟了一段时间。

这不会回答 OP 但确实提供了一种不同的方法并且它处理 CommonsWare 的解决方案不处理的子文件夹,除非你递归(这当然是另一种可能的解决方案)。它专门针对在子文件夹中拥有大量资源的应用。

我添加了一个 ANT 预构建目标来运行这个命令(我在 Windows 上)

dir assets /b /s /A-d > res\raw\assetfiles

这将创建所有文件的递归 (/s)、准系统 (/b) 列表,不包括我的 Assets 文件夹中的目录条目 (/A-d)。

然后我创建了这个类来将 assetfiles 的内容静态加载到一个 hashmap 中,hashmap 的键是文件名,值是完整路径

public class AssetFiles {

// create a hashmap of all files referenced in res/raw/assetfiles

/*map of all the contents of assets located in the subfolder with the name specified in FILES_ROOT
the key is the filename without path, the value is the full path relative to FILES_ROOT
includes the root, e.g. harmonics_data/subfolder/file.extension - this can be passed
directly to AssetManager.open()*/
public static HashMap<String, String> assetFiles = new HashMap<String, String>();
public static final String FILES_ROOT = "harmonics_data";

static {

String line;
String filename;
String path;

try {

BufferedReader reader = new BufferedReader(new InputStreamReader(TidesPlannerApplication.getContext().getResources().openRawResource(R.raw.assetfiles)));

while ((line = reader.readLine()) != null) {
// NB backlash (note the escape) is specific to Windows
filename = line.substring(line.lastIndexOf("\\")+1);
path = line.substring(line.lastIndexOf(FILES_ROOT)).replaceAll("\\\\","/");;
assetFiles.put(filename, path);
}

} catch (IOException e) {
e.printStackTrace();
}

}

public static boolean exists(String filename){
return assetFiles.containsKey(filename);
}

public static String getFilename(String filename){
if (exists(filename)){
return assetFiles.get(filename);
} else {
return "";
}

}

要使用它,我只需调用 AssetFiles.getFilename(filename) 即可返回我可以传递给 AssetManager.open() 的完整路径。快多了!

注意。我还没有完成这个类(class),它还没有强化,所以你需要添加适当的异常捕获和操作。它也非常适合我的应用程序,因为我的所有 Assets 都位于子文件夹中,而这些子文件夹又位于 Assets 文件夹的子文件夹中(请参阅 FILES_ROOT),但很容易适应您的情况。

另请注意,需要替换反斜杠,因为 Windows 会生成带有正斜杠的 Assets 文件列表。您可以在 OSX 和 *nix 平台上消除它。

关于android - 为什么 AssetManger.list() 这么慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12636861/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com