【React Native】差量熱更新(二)

上一篇介紹了在Windows平臺上生成diff.zip和diffMD5.txt的生成工具,接下來介紹在移動端如何使用diffMD5.txt和diff.zip來merge資源和bundle文件,從而差量熱更新。

按照慣例,先講一下整體思想:
1、下載MD5文件,與本地MD5文件進行比對,如果相同,不需要下載diff.zip包,如果不同下載diff.zip
這裏下載MD5文件和比對的邏輯就不再贅述。同樣,下載diff.zip的邏輯也不再贅述。
2、將下載出來的diff.zip進行處理(核心邏輯)
(1)、將diff.zip進行解壓
(2)、將目前的bundle文件和資源文件進行備份,爲將來的回滾處理做準備(目前沒有操作)
(3)、合併bundle文件
(4)、合併資源文件
(5)、備份MD5文件
(6)、刪除diff.zip的解壓文件夾

下面將主要介紹(1)、(3)、(4)的核心邏輯代碼:

(1)、將diff.zip解壓縮:解壓縮的時候只需要注意一點,及目錄結構的還原:如壓縮時文件的目錄爲res/drawable-xhdpi/image.png,壓縮後中間文件夾均會消失,同時文件名稱改爲res/drawable-xhdpi/image.png,在解壓縮時需要將文件名重新還原成原來的目錄結構。

public static boolean decompression(String zipFile, String folderPath) throws ZipException, IOException {
        ZipFile zfile = new ZipFile(zipFile);
        Enumeration zList = zfile.entries();
        ZipEntry ze = null;
        byte[] buf = new byte[1024];
        while (zList.hasMoreElements()) {
            ze = (ZipEntry) zList.nextElement();
            String zeName = ze.getName();
            String basePath = folderPath;
            if (zeName.contains("\\")) {
                String[] dirsNames = zeName.split("\\\\");
                for (int i=0;i<dirsNames.length;i++) {
                    if (i == dirsNames.length-1) {
                        zeName = dirsNames[i];
                        continue;
                    }
                    basePath = basePath + File.separator + dirsNames[i];
                    createDir(basePath);
                }
            }
            OutputStream os = new BufferedOutputStream(
                    new FileOutputStream(getRealFileName(basePath, zeName)));
            InputStream is = new BufferedInputStream(zfile.getInputStream(ze));
            int readLen = 0;
            while ((readLen = is.read(buf, 0, 1024)) != -1) {
                os.write(buf, 0, readLen);
            }
            is.close();
            os.close();
        }
        zfile.close();
        return true;
    }

(3)、合併bundle文件:

public void mergeBundle(Context context) {
        String currentBundleFilePath = FileUtils.getCurrentBundleFilePath(context);
        String diffBundleFilePath = FileUtils.getDiffBundleFilePath(context);
        if ("".equals(currentBundleFilePath) || "".equals(diffBundleFilePath)) {
            return;
        }

        BundleDiffMerge.bundleDiffMerge(currentBundleFilePath,diffBundleFilePath,currentBundleFilePath);//合併bundle文件的核心代碼
    }
/**
     * @param oldBundlePath 爲oldBundle
     * @param diffBundlePath 爲diffBundle
     * @param outputPath 爲輸出newBundle路徑
     */
    public static void bundleDiffMerge(String oldBundlePath,String diffBundlePath,String outputPath) {
        String oldPath = oldBundlePath;
        String diffPath = diffBundlePath;

        diff_match_patch dmp = new diff_match_patch();
        //將text diff轉換爲patch
        LinkedList<diff_match_patch.Patch> pathes = (LinkedList<diff_match_patch.Patch>) dmp.patch_fromText(DiffUtils.getStringFromPat(diffPath));
        //與舊bundle合併  生成新bundle
        Object[] bundleArray = dmp.patch_apply(pathes,getJsBundleFromAssets(oldPath));
        try {
            File outputFile = new File(outputPath);
            if (!outputFile.exists()) {
                outputFile.createNewFile();
            }
            Writer writer = new FileWriter(outputPath);
            String newBundle = (String) bundleArray[0];
            writer.write(newBundle);
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

(4)、合併資源文件

private void mergeRes(Context context) {
        String diffResDirPath = FileUtils.getDiffResDirPath(context);
        if ("".equals(diffResDirPath)) {
            Log.e("------","沒有需要merge的資源");
            return;
        }
        File resFile = new File(diffResDirPath);
        if (resFile.isDirectory()) {
            for (File file : resFile.listFiles()) {
                if (file.isDirectory() && file.getName().contains("drawable")) {
                    //只copy drawable相關的資源文件
                    com.gome.work.diff.utils.FileUtils.copyDir(file.getAbsolutePath(),FileUtils.getRootFile(context).getAbsolutePath() + "/" + file.getName());
                }
            }
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章