Follow by Email

Tuesday, February 12, 2013

Использование assets в Android

    В целом использование Assets в Android не представляет из себя ничего сложного: знай себе читай из InputStream. Но тут есть некоторые подводные камни. В частности производительность, которая при использовании метода list() падает ниже плинтуса. Связано это, по видимому, с тем, что ассеты хранятся в сжатом виде и при каждом считывании приходиться производить манипуляции с архивом. О том как с этим боролся я ниже.

    В случае если вы вынужденны часто вызывать list() имеет смысл закэшировать результаты ее выполнения. Так как assets во время выполнения доступны только на чтения, то в этом нет ничего сложного. Вот класс, который я написал и использую в реальном проекте:

public class AssetsAccessHelper {
 
 private static AssetsAccessHelper helperObj = null;
 private AssetManager am;
 private Map<String, List<String>> assetsMap = new HashMap<String, List<String>>();
 
 public static AssetsAccessHelper getInstance(Context ctx){
  if(helperObj == null)
   helperObj =  new AssetsAccessHelper(ctx);
  return helperObj;
 }
 
 private AssetsAccessHelper(Context ctx){
  am = ctx.getAssets();
 }
 
 private void loadAssetsFolder(String folder) throws IOException{
  String[] fList = am.list(folder);
  assetsMap.put(folder, Arrays.asList(fList));
 }
 
 public String[] list(String folder) throws IOException{
  if(assetsMap.containsKey(folder))
   return assetsMap.get(folder).toArray(new String[assetsMap.get(folder).size()]);
  loadAssetsFolder(folder);
  return list(folder);
 }
 
 public boolean isBaseInAssets(String folder){
  if(assetsMap.containsKey(folder))
   return assetsMap.get(folder).size() == 1;
  try {
   loadAssetsFolder(folder);
  } catch (IOException e) {
   return false;
  }
  return isBaseInAssets(folder);
 }

}
    Как видите ничего сложного, однако при использовании данного подхода удалось сократить  время запуска приложения более чем в два раза.
Спасибо за внимание, хорошего кода.