亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

APK動態加載框架(DL)解析

2019-11-09 15:05:06
字體:
來源:轉載
供稿:網友

目錄(?)[-]

前言項目地址意義DL功能介紹架構解析DL對activity生命周期管理的改進DL對類加載器的支持DL對宿主host和插件plugin通信的支持DL對插件獨立運行的支持DLIntent和DLPluginManager開發規范

轉載請注明出處:http://blog.csdn.net/singwhatiwanna/article/details/39937639 (來自singwhatiwanna的csdn博客)

前言

好久沒有發布新的文章,這次打算發表一下我這幾個月的一個核心研究成果:APK動態加載框架(DL)。這段時間我致力于github的開源貢獻,開源了2個比較有用且有意義的項目,一個是PinnedHeaderExpandableListView,另一個是APK動態加載框架。具體可以參見我的github:https://github.com/singwhatiwanna

本次要介紹的是APK動態加載框架(DL),這個項目除了我以外,還有兩個共同開發者:田嘯(時之沙),宋思宇。

為了更好地理解本文,你需要首先閱讀Android apk動態加載機制的研究這一系列文章,分別為:

Android apk動態加載機制的研究

Android apk動態加載機制的研究(二):資源加載和activity生命周期管理

另外,這個開源項目我起了個名字,叫做DL。本文中的DL均指APK動態加載框架。

項目地址

https://github.com/singwhatiwanna/dynamic-load-apk,歡迎star和fork。

運行效果圖:

意義

這里說說這個開源項目的意義。首先要說的是動態加載技術(或者說插件化)在技術驅動型的公司中扮演這相當重要的角色,當項目越來越龐大的時候,需要通過插件化來減輕應用的內存和cpu占用,還可以實現熱插拔,即在不發布新版本的情況下更新某些模塊。

我幾個月前開始進行這項技術的研究,當時查詢了很多資料,沒有找到很好的開源。目前淘寶、微信等都有成熟的動態加載框架,包括apkplug,但是它們都是不開源的。還有github上有一個開源項目AndroidDynamicLoader,其思想是通過Fragment 以及 schema的方式實習的,這是一種可行的技術方案,但是還有限制太多,這意味這你的activity必須通過Fragment去實現,這在activity跳轉和靈活性上有一定的不便,在實際的使用中會有一些很奇怪的bug不好解決,總之,這還是一種不是特別完備的動態加載技術。然后,我發現,目前針對動態加載這一塊成熟的開源基本還是空白的,不管是國內還是國外。而在公司內部,動態加載作為一項核心技術,也不可能是初級開發人員所能夠接觸到的,于是,我決定做一個成熟點的開源,期待能填補這一塊空白。

DL功能介紹

DL支持很多特性,而這些特性使得插件的開發過程變得透明、高效。

1. plugin無需安裝即可由宿主調起。

2. 支持用R訪問plugin資源3. plugin支持Activity和FragmentActivity(未來還將支持其他組件

4. 基本無反射調用 

5. 插件安裝后仍可獨立運行從而便于調試

6. 支持3種plugin對host的調用模式:   (1)無調用(但仍然可以用反射調用)。   (2)部分調用,host可公開部分接口供plugin調用。 這前兩種模式適用于plugin開發者無法獲得host代碼的情況。

   (3)完全調用,plugin可以完全調用host內容。這種模式適用于plugin開發者能獲得host代碼的情況。

7. 只需引入DL的一個jar包即可高效開發插件,DL的工作過程對開發者完全透明

8. 支持android2.x版本

架構解析

如果大家閱讀過本文頭部提到的兩篇文章,那么對DL的架構應該有大致的了解,本文就不再從頭開始介紹了,而是從如下變更的幾方面進行解析,這些優化使得DL的功能和之前比起來更加強大更加易用使用易于擴展。

1. DL對activity生命周期管理的改進

2. DL對類加載器的支持(DLClassLoader)

3. DL對宿主(host)和插件(plugin)通信的支持

4. DL對插件獨立運行的支持

5. DL對activity隨意跳轉的支持(DLIntent)

6. DL對插件管理的支持(DLPluginManager)

其中5和6屬于加強功能,目前正在dev分支上進行開發(本文暫不介紹),其他功能均在穩定版分支master上。

DL對activity生命周期管理的改進

大家知道,DL最開始的時候采用反射去管理activity的生命周期,這樣存在一些不便,比如反射代碼寫起來復雜,并且過多使用反射有一定的性能開銷。針對這個問題,我們采用了接口機制,將activity的大部分生命周期方法提取出來作為一個接口(DLPlugin),然后通過代理activity(DLPRoxyActivity)去調用插件activity實現的生命周期方法,這樣就完成了插件activity的生命周期管理,并且沒有采用反射,當我們想增加一個新的生命周期方法的時候,只需要在接口中聲明一下同時在代理activity中實現一下即可,下面看一下代碼:

接口DLPlugin

[java] view plain copy public interface DLPlugin {        public void onStart();      public void onRestart();      public void onActivityResult(int requestCode, int resultCode, Intent data);      public void onResume();      public void onPause();      public void onStop();      public void onDestroy();      public void onCreate(Bundle savedInstanceState);      public void setProxy(Activity proxyActivity, String dexPath);      public void onSaveInstanceState(Bundle outState);      public void onNewIntent(Intent intent);      public void onRestoreInstanceState(Bundle savedInstanceState);      public boolean onTouchEvent(MotionEvent event);      public boolean onKeyUp(int keyCode, KeyEvent event);      public void onWindowAttributesChanged(LayoutParams params);      public void onWindowFocusChanged(boolean hasFocus);      public void onBackPressed();  }  在代理類DLProxyActivity中的實現[java] view plain copy ...      @Override      protected void onStart() {          mRemoteActivity.onStart();          super.onStart();      }        @Override      protected void onRestart() {          mRemoteActivity.onRestart();          super.onRestart();      }        @Override      protected void onResume() {          mRemoteActivity.onResume();          super.onResume();      }        @Override      protected void onPause() {          mRemoteActivity.onPause();          super.onPause();      }        @Override      protected void onStop() {          mRemoteActivity.onStop();          super.onStop();      }  ...  說明:通過上述代碼應該不難理解DL對activity生命周期的管理,其中mRemoteActivity就是DLPlugin的實現。

DL對類加載器的支持

為了更好地對多插件進行支持,我們提供了一個DLClassoader類,專門去管理各個插件的DexClassoader,這樣,同一個插件就可以采用同一個ClassLoader去加載類從而避免多個classloader加載同一個類時所引發的類型轉換錯誤。

[java] view plain copy public class DLClassLoader extends DexClassLoader {      private static final String TAG = "DLClassLoader";        private static final HashMap<String, DLClassLoader> mPluginClassLoaders = new HashMap<String, DLClassLoader>();        protected DLClassLoader(String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent) {          super(dexPath, optimizedDirectory, libraryPath, parent);      }        /**      * return a available classloader which belongs to different apk      */      public static DLClassLoader getClassLoader(String dexPath, Context context, ClassLoader parentLoader) {          DLClassLoader dLClassLoader = mPluginClassLoaders.get(dexPath);          if (dLClassLoader != null)              return dLClassLoader;            File dexOutputDir = context.getDir("dex", Context.MODE_PRIVATE);          final String dexOutputPath = dexOutputDir.getAbsolutePath();          dLClassLoader = new DLClassLoader(dexPath, dexOutputPath, null, parentLoader);          mPluginClassLoaders.put(dexPath, dLClassLoader);            return dLClassLoader;      }  }  

DL對宿主(host)和插件(plugin)通信的支持

這一點很重要,因為往往宿主需要和插件進行各種通信,因此DL對宿主和插件的通信做了很好的支持,目前總共有3中模式,如下圖所示:

下面分別介紹上述三種模式,針對上述三種模式,我們分別提供了3組例子,其中:

1. depend_on_host:插件完全依賴宿主的模式,適合于能夠能到宿主的源代碼的情況

其中host指宿主工程,plugin指插件工程

2. depend_on_interface:插件部分依賴宿主的模式,或者說插件依賴宿主提供的接口,適合能夠拿到宿主的接口的情況

其中host指宿主工程,plugin指插件工程,common指接口工程

3. main:插件不依賴宿主的模式,這是DL推薦的模式

其中host指宿主工程,plugin指插件工程

模式1:這是DL推薦的模式,對應的工程目錄為main。在這種模式下,宿主和插件不需要通信,兩者是獨立開發的,宿主引用DL的jar包(dl-lib.jar),插件也需要引用DL的jar包,但是不能放入到插件工程的libs目錄下面,換句話說,就是插件編譯的時候依賴jar包但是打包成apk的時候不要把jar包打進去,這是因為,dl-lib.jar已經在宿主工程中存在了,如果插件中也有這個jar包,就會發生類鏈接錯誤,原因很簡單,內存中有兩份一樣的類,重復了。至于support-v4也是同樣的道理。對于eclipse很簡單,只需要在插件工程中創建一個目錄,比如external-jars,然后把dl-lib.jar和support-v4.jar放進去,同時在.classpath中追加如下兩句即可:

<classpathentry kind="lib" path="external-jars/dl-lib.jar"/><classpathentry kind="lib" path="external-jars/android-support-v4.jar"/>

這樣,編譯的時候就能夠正常進行,但是打包的時候,就不會把上面兩個jar包打入到插件apk中。

至于ant環境和gradle,解決辦法不一樣,具體方法后面再補上,但是思想都是一樣的,即:插件apk中不要打入上述2個jar包。

模式2:插件部分依賴宿主的模式,或者說插件依賴宿主提供的接口,適合能夠拿到宿主的接口的情況。在這種模式下,宿主放出一些接口并實現一些接口,然后給插件調用,這樣插件就可以訪問宿主的一些服務等

模式3:插件完全依賴宿主的模式,適合于能夠能到宿主的源代碼的情況。這種模式一般多用在公司內部,插件可以訪問宿主的所有代碼,但是,這樣插件和宿主的耦合比較高,宿主一動,插件就必須動,比較麻煩

具體采用哪種方式,需要結合實際情況來選擇,一般來說,如果是宿主和插件不是同一個公司開發,建議選擇模式1和模式2;如果宿主和插件都在同一個公司開發,那么選擇哪個都可以。從DL的實現出發,我們推薦采用模式1,真的需要通信的話采用模式2,盡量不要采用模式3.

DL對插件獨立運行的支持

為了便于調試,采用DL所開發的插件都可以獨立運行,當然,這要分情況來說:

對于模式1,如果插件想獨立運行,只需要把external-jars下的jar包拷貝一份到插件的libs目錄下即可

對于模式2,只需要提供一個宿主接口的默認實現即可

對于模式3,只需要apk打包時把所引用的宿主代碼打包進去即可,具體方式可以參看sample/depend_on_host目錄。

在開發過程中,應該先開啟插件的獨立運行功能以便于調試,等功能開發完畢后再將其插件化。

DLIntent和DLPluginManager

這兩項都屬于加強功能,目前正在dev分支進行code review,大家感興趣可以去dev分支上查看,等驗證通過即merge到穩定版master分支。

DLIntent:通過DLIntent來完成activity的無約束調起

DLPluginManager:對宿主的所有插件提供綜合管理功能。

開發規范

目前DL已經達到了第一個穩定版,經過大量機型的驗證,目前得出的結論是DL是可靠的(兼容到android2.x),可以用在實際的應用開發中。但是,我們知道,動態加載是一個技術壁壘,其很難達到一種完美的狀態,畢竟,讓一個apk不安裝跑起來,這是多么不可思議的事情。因此,希望大家辯證地去看這個問題,下面列出我們目前還不支持的功能,或者說是一種開發規范吧,希望大家在開發過程中去遵守這個規范,這樣才能讓插件穩定地跑起來。

DL 1.0開發規范

1. 目前不支持service

2. 目前只支持動態注冊廣播

3. 目前支持Activity和FragmentActivity,這也是常用的activity

4. 目前不支持插件中的assets

5. 調用Context的時候,請適當使用that,大部分常用api是不需要用that的,但是一些不常用api還是需要用that來訪問。that是apk中activity的基類BaseActivity系列中的一個成員,它在apk安裝運行的時候指向this,而在未安裝的時候指向宿主程序中的代理activity,由于that的動態分配特性,通過that去調用activity的成員方法,在apk安裝以后仍然可以正常運行。

6. 慎重使用this,因為this指向的是當前對象,即apk中的activity,但是由于activity已經不是常規意義上的activity,所以this是沒有意義的,但是,當this表示的不是Context對象的時候除外,比如this表示一個由activity實現的接口。

希望能夠給大家帶來一些幫助,希望大家多多支持!

本開源項目地址:https://github.com/singwhatiwanna/dynamic-load-apk,歡迎大家star和fork。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品专区h在线观看| 亚洲美女喷白浆| 欧美肥老太性生活视频| 午夜精品久久久99热福利| 欧美日韩福利视频| 亚洲女成人图区| 粗暴蹂躏中文一区二区三区| 日韩欧美在线观看视频| 国产日韩在线精品av| 亚洲国产精品网站| 欧美日韩福利视频| 国产一区视频在线播放| 中文字幕亚洲无线码在线一区| 国产精品成人一区二区三区吃奶| 91地址最新发布| 国产91精品久久久| 国产精品专区h在线观看| 欧美性精品220| 欧美韩日一区二区| 久久人人爽人人爽爽久久| 日韩在线中文视频| 欧美丰满片xxx777| 色婷婷亚洲mv天堂mv在影片| 日韩在线视频观看正片免费网站| 成人黄色午夜影院| 精品国产老师黑色丝袜高跟鞋| 97在线观看视频| 欧美日韩亚洲国产一区| 亚洲精品456在线播放狼人| 日韩一区二区久久久| 久久久噜噜噜久久中文字免| 亚洲欧美日韩在线一区| 亚洲尤物视频网| 欧美日韩国产色| 性欧美办公室18xxxxhd| 欧美国产亚洲精品久久久8v| 97国产精品人人爽人人做| 国精产品一区一区三区有限在线| 国产精品日韩欧美综合| 国产日韩欧美夫妻视频在线观看| 亚洲国产欧美久久| 91在线免费观看网站| 久久免费视频这里只有精品| 日韩成人网免费视频| 永久免费精品影视网站| 成人免费福利视频| 亚洲老板91色精品久久| 亚洲色图第一页| 国产精品h片在线播放| 久久久久久高潮国产精品视| 欧美大片在线看免费观看| 日韩av免费一区| 国产91精品久久久久久久| 中文字幕亚洲无线码在线一区| 久久久久久这里只有精品| 亚洲综合色av| 国产伦精品一区二区三区精品视频| 亚洲欧美精品在线| 国自在线精品视频| 国产亚洲视频在线观看| 欧美高清视频一区二区| 国产精品女人久久久久久| 国产精品对白刺激| 久久久久久国产三级电影| 国产精品人人做人人爽| 欧美日韩国产在线看| 亚洲夜晚福利在线观看| 亚洲网站在线播放| 国产日韩中文字幕| 日本亚洲欧美成人| 久久精彩免费视频| 国产欧美一区二区三区视频| 久久天天躁狠狠躁夜夜爽蜜月| 国产亚洲一区二区在线| 国产亚洲精品久久久久久牛牛| 久久久av亚洲男天堂| 精品国产1区2区| 欧美日韩中文在线观看| 日韩视频亚洲视频| 欧美成年人在线观看| 色偷偷亚洲男人天堂| 亚洲精品美女免费| 久久久久久亚洲精品不卡| 欧洲精品在线视频| 日韩精品中文字幕久久臀| 欧日韩不卡在线视频| 91精品国产高清自在线看超| 欧美色欧美亚洲高清在线视频| 亚洲女人天堂视频| 日韩中文字幕欧美| 91九色在线视频| 日本成人在线视频网址| 日韩免费在线免费观看| 国产成人综合一区二区三区| 成人444kkkk在线观看| 久久婷婷国产麻豆91天堂| 国产精品美女久久久久久免费| 日韩中文字幕在线视频| 成人免费视频网| 亚洲自拍欧美另类| 国产精品中文久久久久久久| 日韩免费av在线| 亚洲天堂色网站| 91视频免费在线| 91视频-88av| 国产日韩精品在线| 久久久亚洲精品视频| 精品久久久久人成| 日韩免费av一区二区| 免费不卡欧美自拍视频| 45www国产精品网站| 精品久久久久久亚洲精品| 亚洲iv一区二区三区| 亚洲精品乱码久久久久久按摩观| 亚洲精品www久久久久久广东| 久久影视电视剧凤归四时歌| 亚洲高清福利视频| 黑人极品videos精品欧美裸| 久久久亚洲精品视频| 日韩欧美亚洲综合| 日韩av黄色在线观看| 日韩精品高清在线观看| 欧美丰满少妇xxxx| 日韩精品在线免费| 欧美成人性色生活仑片| 成人春色激情网| 国产精品99久久久久久久久久久久| 日韩av第一页| 视频在线观看99| 国产精品色视频| 一区二区三区高清国产| 日韩精品在线电影| 国产精品久久久久福利| 日韩av在线免费| 亚洲free性xxxx护士白浆| 欧美在线视频免费观看| 亚洲国产91精品在线观看| 欧美日韩高清区| 社区色欧美激情 | 欧美天堂在线观看| 68精品国产免费久久久久久婷婷| 国产精品亚洲美女av网站| 77777亚洲午夜久久多人| 91成人在线播放| 在线观看日韩专区| 成人久久久久爱| 国内外成人免费激情在线视频网站| 日韩动漫免费观看电视剧高清| 国产成人精品在线观看| 国产精品福利在线观看网址| 久久精品亚洲94久久精品| 国产午夜精品理论片a级探花| 国产精品日韩欧美综合| 欧美疯狂做受xxxx高潮| 亚洲成人亚洲激情| 欧美国产精品日韩| …久久精品99久久香蕉国产| 久久男人av资源网站| 国产精品视频久久久久| 久久久国产精品一区| 精品国产网站地址| 亚洲激情在线观看视频免费| 中文字幕在线视频日韩| 久久综合网hezyo|