Atlas初探

概念

atlas:容器化框架,提供組件化開發(fā),熱更新。

image

如上圖所示,atlas主要分為以下幾個(gè)層級:

  1. 最底下的hack工具層: 包括了容器所需的所有系統(tǒng)層面的注入和hack的工具類初始化和校驗(yàn),容器啟動(dòng)時(shí)先校驗(yàn)設(shè)備是否支持容器運(yùn)行,不支持則采取降級并記錄原因;
  2. Bundle Framework 負(fù)責(zé)bundle的安裝 更新 操作以及管理整個(gè)bundle的生命周期;
  3. runtime層:主要包括清單管理、版本管理、以及系統(tǒng)代理三大塊,基于不同的觸發(fā)點(diǎn)按需執(zhí)行bundle的安裝和加載;runtime層同時(shí)提供了開發(fā)期快速debug支持和監(jiān)控兩個(gè)功能模塊。從Delegate層可以看到,最核心的兩個(gè)代理點(diǎn):一個(gè)是DelegateClassLoader:負(fù)責(zé)路由class加載到各個(gè)bundle內(nèi)部,第二個(gè)是DelegateResource:負(fù)責(zé)資源查找時(shí)能夠找到bundle內(nèi)的資源;這是bundle能夠真正運(yùn)行起來的根本;其余的代理點(diǎn)均是為了保證在必要的時(shí)機(jī)按需加載起來目標(biāo)bundle,讓其可以被DelegateClassloader和DelegateResource使用
  4. 對外接入層:AtlasBridgeApplication是atlas框架下apk的真正Application,在基于Atlas框架構(gòu)建的過程中會(huì)替換原有manifest中的application,所以Atlas沒入的接入并不存在任何初始化代碼,構(gòu)建腳本完成了接入的過程。AtlasBridgeApplication里面除了完成了Atlas的初始化功能,同時(shí)內(nèi)置了multidex的功能,這樣做的原因有兩個(gè):

很多大型的app不合理的初始化導(dǎo)致用multidex分包邏輯拆分的時(shí)候主dex的代碼就有可能方法數(shù)超過65536,?AtlasBridgeApplication與業(yè)務(wù)代碼完全解耦,所以拆分上面只要保證atlas框架在主dex,其他代碼無論怎么拆分都不會(huì)有問題;
如果不替換Application,那么atlas的初始化就會(huì)在application里面,由于基于Atlas的動(dòng)態(tài)部署實(shí)際上是類替換的機(jī)制,那么這種機(jī)制就會(huì)必然存在包括Application及其import的class等部分代碼在dalvik不支持部署的情況,這個(gè)在使用過程中造成一定成本,需要小心的使用以避免dalivk內(nèi)部class resolve機(jī)制導(dǎo)致部分class沒成功,替換以后該問題得到最好的解決,除atlas本身以外,所有業(yè)務(wù)代碼均可以動(dòng)態(tài)部署;
另外內(nèi)置的原生的multidex在dalvik上面性能并不好,atlas內(nèi)部對其進(jìn)行了優(yōu)化提高了在dalvik上面的體驗(yàn)。

除AtlasBridgeApplication之外,接入層對外提供了部分工具類,包括主動(dòng)install bundle,start bundle,以及獲取全局的application等各種功能。

集成

  1. 工程項(xiàng)目的build.gradle文件依賴插件:


    image
  2. app目錄下的build.gradle使用插件,并且添加相關(guān)依賴


    image

    image

    image
  3. 加載自啟動(dòng)的bundle

switchToActivity("home","com.taobao.firstbundle.FirstBundleActivity");
//通過類名來調(diào)用
 public void switchToActivity(String key,String activityName){
        Intent intent = new Intent();
        intent.setClassName(getBaseContext(),activityName);
        activityGroupDelegate.startChildActivity(framelayout,key,intent);
    }
image

可以看到現(xiàn)在的fistBundle中彈出了一個(gè)toast,message 為“更新一下”,下面修改firstBundle中的代碼,然后熱更新一下

修改toast的message

@Override
    protected void onResume() {
        super.onResume();
        Toast.makeText(this, "單模塊部署1111111", Toast.LENGTH_SHORT).show();
    }

bundle熱更新步驟
1、 app的build.gradle的語句"version = getEnvValue("versionName", "1.0.0");"中修改想要生成的app的versionName(默認(rèn)為1.0.0)

app目錄下執(zhí)行../gradlew clean assembleDebug publish

(生成apk同時(shí)將跟apk同目錄的ap文件發(fā)布到倉庫)

2、 手機(jī)上安裝apk,同時(shí)進(jìn)到動(dòng)態(tài)部署界面(側(cè)邊欄里面劃開點(diǎn)擊進(jìn)入),且手機(jī)連接電腦adb(確保adb devices可見)

///////////////////////////////^^^^^^準(zhǔn)備工作^^^^^^^^^////////////////////////

3、 進(jìn)行一些想要的修改(暫時(shí)不支持manifest的修改,會(huì)在近期上線)

4、 app工程目錄下執(zhí)行../gradlew clean assembleDebug -DapVersion=apVersion -DversionName=newVersion,
其中apVersion為之前打的完整apk的版本,newVersion為此次動(dòng)態(tài)部署要生成的新的版本號(hào)

5、 檢查build/output/tpatch-debug 目錄下文件是否生成,然后執(zhí)行下面的命令(以下為mac下的命令,windows請修改文件分隔符)

adb push build/outputs/tpatch-debug/update.json /sdcard/Android/data/cx.com.atlasdemo11111/cache/update.json
adb push build/outputs/tpatch-debug/patch-*.tpatch /sdcard/Android/data/cx.com.atlasdemo11111/cache

6、 點(diǎn)擊動(dòng)態(tài)部署頁面紅色按鈕執(zhí)行動(dòng)態(tài)部署

更改firstBundle中的代碼,然后
在app目錄下執(zhí)行命令,app/build/outputs/ 會(huì)出現(xiàn)

//DapVersion基準(zhǔn)版本號(hào)      DversionName更新版本號(hào)
../gradlew clean assembleDebug -DapVersion=1.0.0 -DversionName=1.0.1

命令跑完后就會(huì)出現(xiàn)下面的目錄結(jié)構(gòu)

image

執(zhí)行

adb push build/outputs/tpatch-debug/update.json /sdcard/Android/data/cx.com.atlasdemo11111/cache/update.json
adb push build/outputs/tpatch-debug/patch-*.tpatch /sdcard/Android/data/cx.com.atlasdemo11111/cache

然后點(diǎn)擊動(dòng)態(tài)部署按鈕,效果如下

image

可以看到熱更新已經(jīng)成功。

遠(yuǎn)程bundle使用

  1. 遠(yuǎn)程bundle必須在gradle中配置,如上圖
atlas {

    atlasEnabled true
    tBuildConfig {
        autoStartBundles = ['com.taobao.firstbundle'] //自啟動(dòng)bundle配置
        outOfApkBundles = ['remotebundle']//配置遠(yuǎn)程bundle
    }

    manifestOptions{
        addAtlasProxyComponents true
    }


    patchConfigs {
        debug {
            createTPatch true
        }
    }


    buildTypes {
        debug {
            if (apVersion) {
                baseApDependency "com.taobao.android.atlasdemo:AP-debug:${apVersion}@ap"
                patchConfig patchConfigs.debug
            }
        }
    }
}

2.在Application中添加安裝遠(yuǎn)程bundle的回調(diào)

Atlas.getInstance().setClassNotFoundInterceptorCallback(new ClassNotFoundInterceptorCallback() {
            @Override
            public Intent returnIntent(Intent intent) {
                final String className = intent.getComponent().getClassName();
                final String bundleName = AtlasBundleInfoManager.instance().getBundleForComponet(className);

                if (!TextUtils.isEmpty(bundleName) && !AtlasBundleInfoManager.instance().isInternalBundle(bundleName)) {

                    //遠(yuǎn)程bundle
                    Activity activity = ActivityTaskMgr.getInstance().peekTopActivity();
                    File remoteBundleFile = new File(activity.getExternalCacheDir(),"lib" + bundleName.replace(".","_") + ".so");

                    String path = "";
                    if (remoteBundleFile.exists()){
                        path = remoteBundleFile.getAbsolutePath();
                    }else {
                        Toast.makeText(activity, " 遠(yuǎn)程bundle不存在,請確定 : " + remoteBundleFile.getAbsolutePath() , Toast.LENGTH_LONG).show();
                        return intent;
                    }


                    PackageInfo info = activity.getPackageManager().getPackageArchiveInfo(path, 0);
                    try {
                        Atlas.getInstance().installBundle(info.packageName, new File(path));
                    } catch (BundleException e) {
                        Toast.makeText(activity, " 遠(yuǎn)程bundle 安裝失敗," + e.getMessage() , Toast.LENGTH_LONG).show();

                        e.printStackTrace();
                    }

                    activity.startActivities(new Intent[]{intent});

                }

                return intent;
            }
        });

3.把a(bǔ)pp/build/outputs/remote-bundles-debug/libcom_taobao_remotebundle.so 放到sd卡的cache目錄,執(zhí)行命令

adb push build/outputs/remote-bundles-debug/libcom_taobao_remotebunle.so /sdcard/Android/data/cx.com.atlasdemo11111/cache/libcom_taobao_remotebunle.so

點(diǎn)擊添加遠(yuǎn)程bundle看效果


image

可以看到已經(jīng)將遠(yuǎn)程bundle加載成功。

在自己集成的demo中也有很多的坑。跑命令失敗的情況。記錄一下

集成atlas時(shí)的坑

  1. app工程目錄下執(zhí)行../gradlew clean assembleDebug -DapVersion=apVersion -DversionName=newVersion

這個(gè)命令中的apVersion必須是存在的版本號(hào),比如在gradle中設(shè)置的1.0.0,不然會(huì)報(bào)找不到依賴

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.3"
    defaultConfig {
        applicationId "cx.com.atlasdemo11111"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName version //這里的versionName要和腳本中的一致,如果設(shè)置死,在熱修復(fù)merge的時(shí)候不會(huì)起作用
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

3.這個(gè)版本的單模塊調(diào)試模擬還不穩(wěn)定

atlas不得不說是良心之作,這個(gè)demo只是簡單地集成,以供參考。

點(diǎn)擊下載代碼

官方鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,545評論 19 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,983評論 25 709
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,268評論 6 342
  • 夜是那么漫長,透過黑夜我期待看到光明,可卻感覺光明永遠(yuǎn)不會(huì)到來,不過終于不再做惡夢了,因?yàn)橐呀?jīng)習(xí)慣了一次次的嘲諷與...
    清簡如荷閱讀 255評論 0 0
  • 到了談婚論嫁的年紀(jì)了,始終覺得別扭,我自己還沒那個(gè)能力,能夠養(yǎng)活一家人,一直覺得能力缺少,始終不敢表達(dá)愛,我希望的...
    啊貴閱讀 221評論 2 0

友情鏈接更多精彩內(nèi)容