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閱讀 228,156評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,935評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,908評論 2 372

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,623評論 25 708
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,781評論 18 139
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,151評論 4 61
  • 有人說“上帝給你關上一扇門,必定給你打開一扇窗”,都是屁話,現實卻是“給你關上一扇門,再把四周用木板釘死” 生活啊...
    黎梨吖lee閱讀 455評論 0 0
  • 今天畫的樹葉比之前好一點,還是要先涂底色,然后再一步步仔細畫顏色的紋理和深淺。之前都是一直著急地想一步到位,分層涂...
    小也小姐閱讀 267評論 0 1