美文网首页
Android 复制Assets文件到本地实现app初始化缓存

Android 复制Assets文件到本地实现app初始化缓存

作者: Android绝世小菜鸟 | 来源:发表于2017-03-21 21:15 被阅读0次

在对App进行数据加载的时候,会遇到没有网的情况,这个时候,我们会想对上一次加载的数据进行缓存,避免页面出现空白的情况,这种情况一般在加载成功之后,保存到本地,然后在下次加载错误的时候,展示上次的数据就行了,但是会有一个例外,就是当用户第一次下载app,当时并没有打开,在无网的情况下打开了app,这个时候,并没有缓存上一次加载成功的数据,也会出现页面数据大面积的空白的情况(一般公司没这个要求。。。然而我这xx公司)。

解决方式:将初始化数据放在assets目录下,在启动app,例如在闪屏页中复制到本地,然后在第一次打开app加载错误的时候,读取缓存的数据,在下次加载成功之后,使用上一次的数据,可以说该预埋数据只是在上述情况才会有用。看代码:

public class AssetCopyer {

    private String asset_list_fileName;

    private final Context mContext;
    private final AssetManager mAssetManager;
    private File mAppDirectory;

    public AssetCopyer(Context context, String asset_list_fileName) {
        mContext = context;
        mAssetManager = context.getAssets();
        this.asset_list_fileName = asset_list_fileName;
    }

    /**
     *  将assets目录下指定的文件拷贝到sdcard中
     *  @return 是否拷贝成功,true 成功;false 失败
     *  @throws IOException
     */
    public boolean copy() throws IOException {

        List<String> srcFiles = new ArrayList<>();

        //获取系统在SDCard中为app分配的目录,eg:/sdcard/Android/data/$(app's package)
        //该目录存放app相关的各种文件(如cache,配置文件等),unstall app后该目录也会随之删除
        mAppDirectory = mContext.getExternalFilesDir(null);
        if (null == mAppDirectory) {
            return false;
        }

        //读取assets/$(subDirectory)目录下的assets.lst文件,得到需要copy的文件列表
        List<String> assets = getAssetsList();
        for( String asset : assets ) {
            //如果不存在,则添加到copy列表
            if( ! new File(mAppDirectory,asset).exists() ) {
                srcFiles.add(asset);
            }
        }

        //依次拷贝到App的安装目录下
        for( String file : srcFiles ) {
            copy(file);
        }

        return true;
    }

    /**
     *  获取需要拷贝的文件列表(记录在assets/assets.lst文件中)
     *  @return 文件列表
     *  @throws IOException
     */
    protected List<String> getAssetsList() throws IOException {

        List<String> files = new ArrayList<>();

        InputStream listFile = mAssetManager.open(new File(asset_list_fileName).getPath());
        BufferedReader br = new BufferedReader(new InputStreamReader(listFile));
        String path;
        while (null != (path = br.readLine())) {
            files.add(path);
        }
        return files;
    }

    /**
     *  执行拷贝任务
     *  @param asset 需要拷贝的assets文件路径
     *  @return 拷贝成功后的目标文件句柄
     *  @throws IOException
     */
    protected File copy( String asset ) throws IOException {

        InputStream source = mAssetManager.open(new File(asset).getPath());
        File destinationFile = new File(mAppDirectory, asset);

        if(destinationFile.exists()){
            return destinationFile;
        }

        destinationFile.getParentFile().mkdirs();
        OutputStream destination = new FileOutputStream(destinationFile);
        byte[] buffer = new byte[1024];
        int nread;

        while ((nread = source.read(buffer)) != -1) {
            if (nread == 0) {
                nread = source.read();
                if (nread < 0)
                    break;
                destination.write(nread);
                continue;
            }
            destination.write(buffer, 0, nread);
        }
        destination.close();

        return destinationFile;
    }
}

上面是一个拷贝到app目录下的工具类(/sdcard/Android/data/$(app's package)),拷贝原理是,先将assets目录下的需要拷贝的文件名字添加到一个.text文本文件中 eg:

assets.lst.txt

home_banner_01.png
shop_banner_01.png
shop_item_01.png
shop_item_02.png
shop_item_03.png
shop_item_04.png
shop_item_05.png
shop_item_06.png
shop_item_07.png
shop_item_08.png
shop_item_09.png
shop_label_01.png
shop_label_02.png

assets目录:


Paste_Image.png

最后是两个json文件(缓存的策略是使用SharedPreferences 保存json数据,但是图片无法缓存,这个时候就需要将json中的url对应保存在本地的文件名字)。

贴一段json:image_url就是对应的app目录下的文件

{
  "banner_list": [
    {
      "img": "\/sdcard\/Android\/data\/niubi\/files\/shop_banner_01.png"
    }
  ],
  "note_list": [],
  "shop_list": [
    {
      "icon": "",
      "title": "",
      "goods_list_url": "https:\/\/niubi\/shop\/goods\/0\/category-list",
      "category": [
        {
          "row": 1,
          "col": 3,
          "image_url": "\/sdcard\/Android\/data\/niubi\/files\/shop_item_01.png",
          "category_goods_list": "https:\/\/niubi\/shop\/goods\/0\/category-list"
        }
      ]
    },
    {
      "icon": "\/sdcard\/Android\/data\/niubi\/files\/shop_label_01.png",
      "title": "Apple",
      "goods_list_url": "https:\/\/niubi\/shop\/goods\/91\/category-list",
      "category": [
        {
          "row": 1,
          "col": 1,
          "image_url": "\/sdcard\/Android\/data\/niubi\/files\/shop_item_02.png",
          "category_goods_list": "https:\/\/niubi\/shop\/goods\/detail_redirect\/1941"
        },
        {
          "row": 1,
          "col": 1,
          "image_url": "\/sdcard\/Android\/data\/niubi\/files\/shop_item_03.png",
          "category_goods_list": "https:\/\/niubi\/shop\/goods\/detail_redirect\/1931"
        },
        {
          "row": 1,
          "col": 1,
          "image_url": "\/sdcard\/Android\/data\/niubi\/files\/shop_item_04.png",
          "category_goods_list": "https:\/\/niubi\/shop\/goods\/detail_redirect\/1921"
        },
        {
          "row": 1,
          "col": 3,
          "image_url": "\/sdcard\/Android\/data\/niubi\/files\/shop_item_05.png",
          "category_goods_list": "https:\/\/niubi\/shop\/goods\/91\/category-list"
        }
      ]
    },
    {
      "icon": "\/sdcard\/Android\/data\/niubi\/files\/shop_label_02.png",
      "title": "\u7f8e\u5986",
      "goods_list_url": "https:\/\/niubi\/shop\/goods\/34\/category-list",
      "category": [
        {
          "row": 1,
          "col": 1,
          "image_url": "\/sdcard\/Android\/data\/niubi\/files\/shop_item_06.png",
          "category_goods_list": "https:\/\/niubi\/shop\/goods\/detail_redirect\/2161"
        },
        {
          "row": 1,
          "col": 1,
          "image_url": "\/sdcard\/Android\/data\/niubi\/files\/shop_item_07.png",
          "category_goods_list": "https:\/\/niubi\/shop\/goods\/detail_redirect\/2171"
        },
        {
          "row": 1,
          "col": 1,
          "image_url": "\/sdcard\/Android\/data\/niubi\/files\/shop_item_08.png",
          "category_goods_list": "https:\/\/niubi\/shop\/goods\/detail_redirect\/2191"
        },
        {
          "row": 1,
          "col": 3,
          "image_url": "\/sdcard\/Android\/data\/niubi\/files\/shop_item_09.png",
          "category_goods_list": "https:\/\/niubi\/shop\/goods\/34\/category-list"
        }
      ]
    }
  ]
}
      

再看下加载的具体使用步骤:
1.在闪屏页中 : 复制assets目录下的文件

new Thread(new Runnable() {
          @Override
          public void run() {
              AssetCopyer assetCopyer = new AssetCopyer(SplashActivity.this,"assets.lst");
              try {
                  assetCopyer.copy();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }).start();

2.加载数据:

HttpKit.me().post(params, new JSONCallback<HomePageNew>() {

            @Override
            public void onError(ApiException e) {
                super.onError(e);
                loadErrorData();
            }

            @Override
            public void onResponse(HomePageNew response) {
              (sharedPreferences工具类)
                StorageManager.getInstance().insert("homepage", mHomePageNew);//保存json数据到本地
                ...........更新页面操作
                ...........
            }
        });

//加载错误的时候页面展示
private void loadErrorData() {
        if (mHomePageNew != null) {
            return;
        }
        mHomePageNew = StorageManager.getInstance().query("homepage", HomePageNew.class);
        if (mHomePageNew != null) {//如果获取保存在本地的数据不为null,就使用保存在本地的数据
              。。。。。。。。。。。。
        } else {//第一次打开app无缓存并且无网的情况下,设置一个默认的数据 读取json数据,展示
            String jsonString = null;
            try {
                InputStream home_json_txt = AppKit.me.getAssets().open("rwh_home_data.json");
                int available = home_json_txt.available();
                byte[] bytes = new byte[available];
                home_json_txt.read(bytes);
                home_json_txt.close();
                jsonString = new String(bytes).trim();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            if (jsonString != null) {
                HomePageNew homePageNew = GsonKit.fromJson(jsonString, HomePageNew.class);
                if (homePageNew != null) {
                  。。。。。。。。。。。//更新页面操作
                }
            }
        }
    }


上面就基本完成了所要的需求。

相关文章

网友评论

      本文标题:Android 复制Assets文件到本地实现app初始化缓存

      本文链接:https://www.haomeiwen.com/subject/czzgnttx.html