日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

AndFix解析——(上)

發布時間:2025/3/15 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AndFix解析——(上) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

阿里巴巴前一段時間開源了他們用來解決線上緊急bug的一款Android庫——AndFix

對Android開發者來說真是一個很好的消息。

基于自己的經驗,太長的文字很少有人可以一口氣看下來的,所以我打算分成多篇來分析?這是這個庫解析的第一篇,

我們先看一下其中的Demo代碼,其中調用加載庫的代碼如下所示:

/*** sample application* * @author sanping.li@alipay.com* */ public class MainApplication extends Application {private static final String TAG = "euler";private static final String APATCH_PATH = "/out.apatch";/*** patch manager*/private PatchManager mPatchManager;@Overridepublic void onCreate() {super.onCreate();// initializemPatchManager = new PatchManager(this);mPatchManager.init("1.0");Log.d(TAG, "inited.");// load patchmPatchManager.loadPatch();Log.d(TAG, "apatch loaded.");// add patch at runtimetry {// .apatch file pathString patchFileString = Environment.getExternalStorageDirectory().getAbsolutePath() + APATCH_PATH;mPatchManager.addPatch(patchFileString);Log.d(TAG, "apatch:" + patchFileString + " added.");} catch (IOException e) {Log.e(TAG, "", e);}} }

可以看到代碼中首先通過PatchManager的構造函數初始化了PatchManager對象,

PatchManager構造函數

那么PatchManager對象里面都有什么呢,我們深入其中了解一下。

public PatchManager(Context context) {this.mContext = context;this.mAndFixManager = new AndFixManager(this.mContext);this.mPatchDir = new File(this.mContext.getFilesDir(), "apatch");this.mPatchs = new ConcurrentSkipListSet();this.mLoaders = new ConcurrentHashMap(); }

原來維持了一個Context對象的引用,初始化了AndFixManager對象,mPatchDir對象為存放Patch文件的文件夾,初始化了Patch的集合,還有持有ClassLoader的Map

其中一些內容的聲明如下:

private final Context mContext; private final AndFixManager mAndFixManager; private final File mPatchDir; private final SortedSet<Patch> mPatchs; private final Map<String, ClassLoader> mLoaders;

我們對構造函數的分析在這里就結束了,我們先不深入的跟進Patch和AndFixManager這兩個類了。

PatchManager init(String version)

接下來分析PatchManager類中的init(String version)函數, 先來看代碼

public void init(String appVersion) {//如果mPatchDir不存在,則創建文件夾,如果創建失敗,則打印Logif(!this.mPatchDir.exists() && !this.mPatchDir.mkdirs()) {Log.e("PatchManager", "patch dir create error.");} else if(!this.mPatchDir.isDirectory()) {//如果遇到同名的文件,則將該同名文件刪除this.mPatchDir.delete();} else {//在該文件下放入一個名為_andfix_的SharedPreferences文件,SharedPreferences sp = this.mContext.getSharedPreferences("_andfix_", 0);String ver = sp.getString("version", (String)null);if(ver != null && ver.equalsIgnoreCase(appVersion)) {this.initPatchs();} else {this.cleanPatch();sp.edit().putString("version", appVersion).commit();}} }

接下來我們分析上面代碼中的如下代碼

//如果從_andfix_這個文件獲取的ver不是null,而且這個ver和外部初始化時傳進來的版本號一致 if(ver != null && ver.equalsIgnoreCase(appVersion)) {this.initPatchs(); } else {this.cleanPatch();sp.edit().putString("version", appVersion).commit(); }

先看else內的內容,else里執行力cleanPatch()和把外部初始化的時候傳進來的版本號放入SharedPreferences里。?cleanPatch()做了什么操作呢,我們跟進去看一看

private void cleanPatch() {//獲取mPatchDir目錄下所有文件File[] files = this.mPatchDir.listFiles();File[] arr$ = files;int len$ = files.length;for(int i$ = 0; i$ < len$; ++i$) {File file = arr$[i$];//將此文件從OptFile文件夾刪除this.mAndFixManager.removeOptFile(file);//這個方法的作用就是如果file是文件,則刪除它,如果file是文件夾,則將它和它里面的文件都刪除if(!FileUtil.deleteFile(file)) {Log.e("PatchManager", file.getName() + " delete error.");}} }

如源碼中的注釋,就是刪除了之前在那兩個文件夾下的所有的補丁文件。

現在來分析一下this.initPatchs()做了什么事

private void initPatchs() {File[] files = this.mPatchDir.listFiles();File[] arr$ = files;int len$ = files.length;for(int i$ = 0; i$ < len$; ++i$) {File file = arr$[i$];this.addPatch(file);} }

代碼很簡單,就是把mPatchDir文件夾下的文件作為參數傳給了addPatch(File)方法 那this.addPatch(file)做了什么呢

//把擴展名為.apatch的文件傳給Patch做參數,初始化對應的Patch, //并把剛初始化的Patch加入到我們之前看到的Patch集合mPatchs中 private Patch addPatch(File file) { Patch patch = null;//擴展名是否為".apatch"if(file.getName().endsWith(".apatch")) {try {patch = new Patch(file);this.mPatchs.add(patch);} catch (IOException var4) {Log.e("PatchManager", "addPatch", var4);}}return patch; }

上面的代碼很好理解,此時,我們已經完整的走下來了init(String version)這個方法。 再次出現了Patch這個類,但是我們依然要把它放在一邊,因為由于篇幅限制,第一篇不會分析這個類。

接下來,我們繼續跟著demo走,會執行兩個方法,一個mPatchManager.loadPatch(),一個mPatchManager.addPatch(patchFileString),?loadPatch()方法是這個庫執行替換的核心方法,我會在以后單獨寫一篇文章來分析,所以,在這篇文章的最后,我們跟進addPatch(String)這個方法一看究竟

public void addPatch(String path) throws IOException {File src = new File(path);File dest = new File(this.mPatchDir, src.getName());if(dest.exists()) {//在mPatchDir文件夾下存在該文件,則AndFixManager移除該文件this.mAndFixManager.removeOptFile(dest);}//將文件從src復制到dest,只不過阿里用了NIO來復制文件FileUtil.copyFile(src, dest);//調用了另外一個addPatch方法,以文件作為參數Patch patch = this.addPatch(dest);if(patch != null) {//同樣調用了loadPatch(Patch)方法this.loadPatch(patch);}}

簡單來說,上面的方法就是將補丁文件復制到/data/data/{包名}/apatch 目錄內,如果在OptFile文件夾中存在,則刪除。 然后調用另外一個addPatch(File)方法,然后loadPatch()?下面,我們來看一下重載的addPatch(File)方法

private Patch addPatch(File file) {Patch patch = null;if(file.getName().endsWith(".apatch")) {try {patch = new Patch(file);//把從file文件生成的patch加入到mPatchs這個Set中this.mPatchs.add(patch);} catch (IOException var4) {Log.e("PatchManager", "addPatch", var4);}}return patch; }

該方法主要做的事情在注釋中即可了解,到這里,第一篇分析就結束了。


原文地址: http://yunair.github.io/blog/2015/09/25/AndFix-%E8%A7%A3%E6%9E%90(%E4%B8%8A).html

總結

以上是生活随笔為你收集整理的AndFix解析——(上)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。