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

在对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) {
                  。。。。。。。。。。。//更新页面操作
                }
            }
        }
    }


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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,397评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 有人说“上帝给你关上一扇门,必定给你打开一扇窗”,都是屁话,现实却是“给你关上一扇门,再把四周用木板钉死” 生活啊...
    黎梨吖lee阅读 443评论 0 0
  • 今天画的树叶比之前好一点,还是要先涂底色,然后再一步步仔细画颜色的纹理和深浅。之前都是一直着急地想一步到位,分层涂...
    小也小姐阅读 260评论 0 1