1. Android 組件化
- 組件化開(kāi)發(fā)可以有效降低代碼模塊的耦合度,使代碼架構(gòu)更加清晰,同時(shí)模塊化的編譯可以有效減少編譯時(shí)間,當(dāng)然總的編譯時(shí)間是不會(huì)減少的畦木,只是App模塊化之后開(kāi)發(fā)某個(gè)模塊時(shí),只需要編譯特定模塊砸泛,可以快速編譯調(diào)試
- 將一個(gè)Module拆分成若干個(gè)Module十籍,由主App提供統(tǒng)一的入口,每個(gè)拆分后的Module都依賴共享的Common依賴庫(kù)唇礁,通過(guò)相關(guān)配置勾栗,各個(gè)Module可以獨(dú)立運(yùn)行調(diào)試,也可以供主App依賴使用盏筐。
- ARouter 原理
ARouter
核心實(shí)現(xiàn)思路是围俘,我們?cè)诖a里加入的@Route
注解,會(huì)在編譯時(shí)期通 過(guò)apt
生成一些存儲(chǔ)path
和activityClass
映射關(guān)系的類(lèi)文件琢融,然后app
進(jìn)程啟動(dòng)的時(shí)候會(huì)拿到這些類(lèi)文件界牡,把保存這些映射關(guān)系的數(shù)據(jù)讀到內(nèi)存里(保存在 map 里)
,然后在進(jìn)行路由跳轉(zhuǎn)的時(shí)候漾抬,通過(guò)build()
方法傳入要到達(dá)頁(yè)面的路由 地址欢揖,ARouter
會(huì)通過(guò)它自己存儲(chǔ)的路由表找到路由地址對(duì)應(yīng)的Activity.class(activity.class = map.get(path))
,然后new Intent()
奋蔚,當(dāng)調(diào)用ARouter
的withString()
方法它的內(nèi)部會(huì)調(diào)用intent.putExtra(String name, String value)
, 調(diào)用navigation()
方法烈钞,它的內(nèi)部會(huì)調(diào)用startActivity(intent)
進(jìn)行跳轉(zhuǎn)泊碑,這樣便可 以實(shí)現(xiàn)兩個(gè)相互沒(méi)有依賴的module
順利的啟動(dòng)對(duì)方的Activity
.
3.1 ARouter
的原理就是所有的moudle
都引用ARouter
,然后再moudle
中去生成一個(gè)映射表毯欣,然后再把這個(gè)映射表傳到ARouter
中
3.2 映射表生成 , 我們一般配置ARouter會(huì)這樣寫(xiě)
@Route(path = xxx/xxx)
public class xxx{
......
}
3.3 發(fā)起跳轉(zhuǎn)
ARouter.getInstance().build("/user/UserMainActivity").navigation()
ARouter的代碼要簡(jiǎn)潔很多馒过,完全不需要手動(dòng)注冊(cè)路由就可完成跳轉(zhuǎn),它是怎么做到的呢酗钞?
3.4 很神奇腹忽!與前篇我們實(shí)現(xiàn)的路由相比,ARouter的代碼要簡(jiǎn)潔很多砚作,完全不需要手動(dòng)注冊(cè)路由就可完成跳轉(zhuǎn)窘奏,它是怎么做到的呢?
通過(guò)跟進(jìn)navigation()函數(shù)調(diào)用過(guò)程葫录,我們把目光聚焦到兩個(gè)容器中:
// ARouter源碼
class Warehouse {
// Cache route and metas
//用于存儲(chǔ)所有的路由組
static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>();
//用于存儲(chǔ)已注冊(cè)的所有路由
static Map<String, RouteMeta> routes = new HashMap<>();
...
}
public interface IRouteGroup {
/**
* Fill the atlas with routes in group.
* atlas用于存儲(chǔ)當(dāng)前組里的所有路由着裹,實(shí)際傳入的就是Warehouse.routes
*/
void loadInto(Map<String, RouteMeta> atlas);
}
// 路由包裝類(lèi),路由目標(biāo)的Class對(duì)象就存儲(chǔ)在這里面
public class RouteMeta {
private RouteType type; // Type of route
private Element rawType; // Raw type of route
private Class<?> destination; // Destination
private String path; // Path of route
private String group; // Group of route
private int priority = -1; // The smaller the number, the higher the priority
private int extra; // Extra data
private Map<String, Integer> paramsType; // Param type
private String name;
...
}
- ARouter對(duì)路由提出了分組概念米同,上面 UserMainActivity就屬于user組下骇扇,當(dāng)路由path存在2級(jí)及以上時(shí)摔竿,group字段也可以省略,ARouter默認(rèn)會(huì)使用第一個(gè)反斜杠后面的path作為組名
// group可省略不寫(xiě)
@Route(path = "/user/UserMainActivity")
class UserMainActivity : AppCompatActivity() {
...
}
- 一般情況下少孝,我們會(huì)將同一模塊的路由劃分在同一個(gè)組下继低,例如App模塊下的所有路由都在“app”這個(gè)分組下 , user模塊的路由都在“user”分組下;當(dāng)然稍走,同一模塊擁有多個(gè)分組也是完全可行的袁翁,只要保證與其它模塊中的路由分組不重名即可
分析這兩個(gè)容器的作用,大致如下:
1钱磅、當(dāng)傳入path進(jìn)行跳轉(zhuǎn)時(shí)梦裂,優(yōu)先從Warehouse.routes中直接獲取路由對(duì)象;
2盖淡、路由對(duì)象不存在年柠,就需要通過(guò)Warehouse.groupsIndex路由組來(lái)完成注冊(cè)功能
3、注冊(cè)成功后褪迟,當(dāng)前path所在組的所有路由都將存儲(chǔ)到Warehouse.routes中冗恨;
4、回到第1步味赃,獲取路由對(duì)象掀抹;
5、讀取路由對(duì)象信息心俗;
6傲武、完成跳轉(zhuǎn)
2. Android 插件化
- 隨著apk越來(lái)越大,各種業(yè)務(wù)邏輯越來(lái)越繁雜城榛,會(huì)達(dá)到apk開(kāi)發(fā)的一個(gè)瓶頸揪利;從業(yè)務(wù)上說(shuō),業(yè)務(wù)的繁雜會(huì)導(dǎo)致代碼急劇的膨脹狠持,當(dāng)代碼中的方法數(shù)超過(guò)65535時(shí)疟位,就無(wú)法再容納創(chuàng)建新的方法。插件化時(shí)將 apk 分為宿主和插件部分喘垂,插件在需要的時(shí)候才加載進(jìn)來(lái).
- 插件化的優(yōu)點(diǎn)
- 宿主和插件分開(kāi)編譯
- 并發(fā)開(kāi)發(fā)甜刻,宿主和插件都是apk,開(kāi)發(fā)是互不影響的正勒,只需要宿主給插件一個(gè)上下文
- 動(dòng)態(tài)更新插件得院,不需要安裝,下載之后就可以直接打開(kāi)
- 按需下載模塊
- 可以解決方法數(shù)或變量數(shù)爆棚問(wèn)題
-
Android
中的ClassLoader
在Android系統(tǒng)中ClassLoader
是用來(lái)加載dex文件的昭齐,有包含 dex 的 apk 文件以及 jar 文件尿招,dex 文件是一種對(duì)class文件優(yōu)化的產(chǎn)物,在Android中應(yīng)用打包時(shí)會(huì)把所有class文件進(jìn)行合并、優(yōu)化(把不同的class文件重復(fù)的東西只保留一份)就谜,然后生成一個(gè)最終的class.dex文件
-
-
PathClassLoader用來(lái)加載系統(tǒng)類(lèi)和應(yīng)用程序類(lèi)怪蔑,可以加載已經(jīng)安裝的
apk
目錄下的dex
文件
-
PathClassLoader用來(lái)加載系統(tǒng)類(lèi)和應(yīng)用程序類(lèi)怪蔑,可以加載已經(jīng)安裝的
public class PathClassLoader extends BaseDexClassLoader {
public PathClassLoader(String dexPath, ClassLoader parent) {
super(dexPath, null, null, parent);
}
public PathClassLoader(String dexPath, String libraryPath,
ClassLoader parent) {
super(dexPath, null, libraryPath, parent);
}
}
-
DexClassLoader用來(lái)加載
dex
文件,可以從存儲(chǔ)空間加載dex
文件丧荐。
-
DexClassLoader用來(lái)加載
public class DexClassLoader extends BaseDexClassLoader {
public DexClassLoader(String dexPath, String optimizedDirectory,
String libraryPath, ClassLoader parent) {
super(dexPath, new File(optimizedDirectory), libraryPath, parent);
}
}
插件化中一般使用的是
DexClassLoader
3. 組件化和插件化的區(qū)別 ?
- 組件化 : 是將一個(gè)App分成多個(gè)模塊缆瓣,每個(gè)模塊都是一個(gè)組件(module),開(kāi)發(fā)過(guò)程中可以讓這些組件相互依賴或獨(dú)立編譯虹统、調(diào)試部分組件弓坞,但是這些組件最終會(huì)合并成一個(gè)完整的Apk去發(fā)布到應(yīng)用市場(chǎng)。
- 插件化 : 是將整個(gè)App拆分成很多模塊车荔,每個(gè)模塊都是一個(gè)Apk(組件化的每個(gè)模塊是一個(gè)lib)渡冻,最終打包的時(shí)候?qū)⑺拗鰽pk和插件Apk分開(kāi)打包,只需發(fā)布宿主Apk到應(yīng)用市場(chǎng)忧便,插件Apk通過(guò)動(dòng)態(tài)按需下發(fā)到宿主Apk