Why is AssetManger.list() so slow?

后端 未结 4 826
遥遥无期
遥遥无期 2021-01-18 03:25

I\'m trying to populate a ListView with a mixture of files stored on the SDcard AND stored as assets in the APK. Using TraceView, I can see that the performanc

4条回答
  •  一个人的身影
    2021-01-18 04:10

    Coverdriven's comment "stored in a table somewhere" inspired me to solve my own problem which I've been putting off for a while.

    This doesn't answer the OP but does offer a different approach and it handles subfolders which CommonsWare's solution doesn't unless you go recursive (which of course is another possible solution). It's specifically aimed at apps which have a large number of assets in subfolders.

    I added an ANT pre-build target to run this command (I'm on Windows)

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

    This creates a recursive (/s), barebones (/b) listing of all files, excluding directory entries (/A-d) in my assets folder.

    I then created this class to statically load the contents of assetfiles into a hashmap, the key of which is the filename and the value the full path

    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 assetFiles = new HashMap();
    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 "";
        }
    
    }
    

    }

    To use it, I simply call AssetFiles.getFilename(filename) which returns the full path which I can pass to AssetManager.open(). Much much faster!

    NB. I haven't finished this class and it's not hardened yet so you'll need to add appropriate exception catches and actions. It's also quite specific to my app in that all of my assets are in subfolders which are in turn located in a subfolder of the assets folder (see FILES_ROOT) but easy to adapt to your situation.

    Note also the need to replace backslashes, since Windows generates the assetfiles listing, with forward slashes. You could eliminate this on OSX and *nix platforms.

提交回复
热议问题