久久综合给合久久狠狠狠97色69,污视频网站在线免费观看,国产黄色在线免费观看,精品欧美一区二区三区,国产日韩三级,xf在线a精品一区二区视频网站,国产在线98福利播放视频,国产精品99久久久久久宅男,成人福利免费网站,大陆精大陆国产国语精品

當(dāng)前位置:首頁 > 國內(nèi) >

環(huán)球要聞:插件化工程R文件瘦身技術(shù)方案 | 京東云技術(shù)團(tuán)隊2023-06-13 11:28:23 | 編輯:admin | 來源:博客園

隨著業(yè)務(wù)的發(fā)展及版本迭代,客戶端工程中不斷增加新的業(yè)務(wù)邏輯、引入新的資源,隨之而來的問題就是安裝包體積變大,前期各個業(yè)務(wù)模塊通過無用資源刪減、大圖壓縮或轉(zhuǎn)上云、AB實驗業(yè)務(wù)邏輯下線或其他手段在降低包體積上取得了一定的成果。

在瘦身的過程中我們關(guān)注到了R文件瘦身的概念,目前京東APP是支持插件化的,有業(yè)務(wù)插件工程、宿主工程,對業(yè)務(wù)插件包文件進(jìn)行分析,發(fā)現(xiàn)除了常規(guī)的資源及代碼外,R類文件大概占包體積的3%~5%左右,對宿主工程包文件進(jìn)行分析,R類文件占比也有3%左右。我們先后在對R類文件瘦身的可行性及業(yè)界開源項目進(jìn)行調(diào)研后,探索出了一套適用于插件化工程的R文件瘦身技術(shù)方案。


【資料圖】

理論基礎(chǔ)—R文件

R文件也就是我們?nèi)粘9ぷ髦薪?jīng)常打交道的R.java文件,在Android開發(fā)規(guī)范中我們需要將應(yīng)用中用到的資源分別放入專門命名的資源目錄中,外部化應(yīng)用資源以便對其進(jìn)行單獨維護(hù)。

外部化應(yīng)用資源后,我們可在項目中使用R類ID來訪問這些資源,且R類ID具有唯一性。

public class MainActivity  extends BaseActivity {    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }}

在android apk打包流程中R類文件是由aapt(Android Asset Packaing Tool)工具打包生成的,在生成R類文件的同時對資源文件進(jìn)行編譯,生成resource.arsc文件,resource.arsc文件相當(dāng)于一個文件索引表,應(yīng)用層代碼通過R類ID 可以訪問到對應(yīng)的資源。

R文件瘦身的可行性分析

日常開發(fā)階段,在主工程中通過R.xx.xx的方式引用資源,經(jīng)過編譯后R類引用對應(yīng)的常量會被編譯進(jìn)class中。

setContentView(2131427356);

這種變化叫做內(nèi)聯(lián),內(nèi)聯(lián)是java的一種機制(如果一個常量被標(biāo)記為static final,在java編譯的過程中會將常量內(nèi)聯(lián)到代碼中,減少一次變量的內(nèi)存尋址)。

非主工程中,R類資源ID以引用的方式編譯進(jìn)class中,不會產(chǎn)生內(nèi)聯(lián)。

setContentView(R.layout.activity_main);

產(chǎn)生這種現(xiàn)象的原因是AGP打包工具導(dǎo)致的。具體細(xì)節(jié),大家可以去查閱一下android gradle plugin在R文件上的處理過程。

結(jié)論:R類id內(nèi)聯(lián)后程序可運行,但并非所有的工程都會自動產(chǎn)生內(nèi)聯(lián)現(xiàn)象,我們需要通過技術(shù)手段在合適的時機將R類id內(nèi)聯(lián)到程序中,內(nèi)聯(lián)完成后,由于不再依賴R類文件,則可以將R類文件刪除,在應(yīng)用正常運行的同時,達(dá)到包瘦身目的。

插件化工程R文件瘦身實戰(zhàn)制定技術(shù)方案

目前京東Android客戶端是支持插件化的,整個插件化工程包含公共庫(是一個aar工程,用來存放組件和宿主共用的類和資源)、業(yè)務(wù)插件(插件工程是一個獨立的工程,編譯產(chǎn)物可以運行在宿主環(huán)境中)、宿主(主工程,提供運行環(huán)境)。在插件化的過程中為了防止宿主和插件資源沖突,通過修改插件packageId保證了資源的唯一性。由于公共資源庫、宿主是被很多業(yè)務(wù)依賴,對這兩個項目進(jìn)行改動評估影響涉及比較多,插件一般都是業(yè)務(wù)模塊自行維護(hù),不存在被依賴問題,所以先在業(yè)務(wù)插件模塊進(jìn)行R類瘦身實踐。

對業(yè)務(wù)插件工程打出的包進(jìn)行反編譯以后,發(fā)現(xiàn)R類ID無內(nèi)聯(lián)現(xiàn)象,且R類文件具有一定的大小,對包內(nèi)的R文件進(jìn)行分析,發(fā)現(xiàn)R文件中僅包含業(yè)務(wù)自身的資源,不包含業(yè)務(wù)依賴的公共資源R類。

public View onCreateView(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup, Bundle paramBundle) {    this.b = paramLayoutInflater.inflate(R.layout.lib_pd_main_page, paramViewGroup, false);    this.h = (PDBuyStatusView)this.b.findViewById(R.id.pd_buy_status_view);    this.f = (PageRecyclerView)this.b.findViewById(R.id.lib_pd_recycle_view);}

結(jié)合對業(yè)界開源項目的調(diào)研分析,嘗試制定符合京東商城的技術(shù)方案并優(yōu)先在業(yè)務(wù)插件內(nèi)完成R類ID內(nèi)聯(lián)并刪除對應(yīng)的R文件。

1.通過transformapi 收集要處理的class文件

Transform 是 Android Gradle 提供的操作字節(jié)碼的一種方式,它在 class 編譯成 dex 之前通過一系列 Transform 處理來實現(xiàn)修改.class文件。

@Overridepublic void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException {super.transform(transformInvocation);//  通過TransformInvocation.getInputs()獲取輸入文件,有兩種//  DirectoryInpu以源碼方式參與編譯的目錄結(jié)構(gòu)及目錄下的文件//  JarInput以jar包方式參與編譯的所有jar包    allDirs = new ArrayList<>(invocation.getInputs().size());    allJars = new ArrayList<>(invocation.getInputs().size());    Collection inputs = invocation.getInputs();    for (TransformInput input : inputs) {        Collection directoryInputs = input.getDirectoryInputs();         for (DirectoryInput directoryInput : directoryInputs) {               allDirs.add(directoryInput.getFile());             }            Collection jarInputs = input.getJarInputs();         for (JarInput jarInput : jarInputs) {                allJars.add(jarInput.getFile());             }     }}
2.對收集到的.class文件結(jié)合ASM框架進(jìn)行分析處理

ASM是一個操作Java字節(jié)碼的類庫,通過ASM我們可以方便對.class文件進(jìn)行修改。

優(yōu)先識別R類文件,通過ClassVisitor訪問R.class文件,讀取文件中的靜態(tài)常量,進(jìn)行臨時變量存儲:

@Overridepublic FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {    //R類中收集 public static final int 對應(yīng)的變量  if (JDASMUtil.isPublic(access) && JDASMUtil.isStatic(access) &&JDASMUtil.isFinal(access) &&JDASMUtil.isInt(desc)) {       jdRstore.addInlineRField(className, name, value);      }      return super.visitField(access, name, desc, signature, value);}

非R類文件,通過MethodVisitor識別到代碼中的R類引用,獲取引用對應(yīng)的值,進(jìn)行id值替換:

@Override    public void visitFieldInsn(int opcode, String owner, String name, String desc) {        if (opcode == Opcodes.GETSTATIC) {            //owner:包名;name:具體變量名;value:R類變量對應(yīng)的具體id值            Object value = jdRstore.getRFieldValue(owner, name);            if (value != null) {              //調(diào)用該api實現(xiàn)值替換                mv.visitLdcInsn(value);                return;            }        }        super.visitFieldInsn(opcode, owner, name, desc);    }

*注:以上代碼僅為部分示意代碼,非正式插件代碼。

在業(yè)務(wù)模塊引入R類瘦身插件后,業(yè)務(wù)模塊功能可正常運行,且插件包大小均有3%~5%不同程度的減少。

公共資源R類ID內(nèi)聯(lián)

由于在京東android客戶端代碼中,更多的資源文件集中在公共資源庫中,相對的公共庫生成的R類文件也更大,對編譯后的apk包內(nèi)容進(jìn)行分析后,公共資源庫的R類文件占比高達(dá)3%。

公共庫跟隨宿主一起打包,在宿主打包過程中引入R類瘦身插件,打包后的apk有明顯的減小,手機安裝apk后啟動首頁正常展示無問題,但在打開某些業(yè)務(wù)插件時,會有異常閃退現(xiàn)象,崩潰類型為R.x resource not found。對崩潰原因分析如下:業(yè)務(wù)插件代碼中使用了公共庫中的R類資源、插件打包流程獨立于宿主打包,在插件打包的過程中僅完成了業(yè)務(wù)模塊R類的內(nèi)聯(lián),并沒有考慮到公共資源R類的內(nèi)聯(lián),基于上述原因當(dāng)宿主打包過程完成R類文件刪除瘦身后,我們在運行某業(yè)務(wù)插件的過程中,自然就會報公共資源R類找不到的問題從而產(chǎn)生崩潰。

為了解決這個問題一開始的方案設(shè)想是增加白名單機制,keep住所有被業(yè)務(wù)模塊使用的公共資源,但很快這個想法就被推翻,公共資源存在本身就是希望各個業(yè)務(wù)模塊直接引用這部分資源,而不是自己定義,如果keep住的話,必然有很大一部分的資源無法刪減,瘦身的效果會大打折扣。

既然保留的方案并不合適,那就將公共資源R類id也內(nèi)聯(lián)到代碼中去。前面提到京東是支持插件化的,整個插件化方案是基于aura平臺實現(xiàn)的,我們向aura團(tuán)隊進(jìn)行了咨詢,然后get到了新的方案切入點。

aura平臺在插件化的過程中已通過aapt2引入了公共資源id固定的能力,在該能力下,已定義的公共資源id會一直固定(各個業(yè)務(wù)插件中引用的公共資源id一致),且公共資源庫中已有的資源不可被其他模塊重復(fù)定義,否則會覆蓋之前已定義好的資源,基于上述的結(jié)果和規(guī)則,我們對之前的R文件瘦身gralde plugin功能進(jìn)行完善,將公共資源的R類id 內(nèi)聯(lián)到項目中。

利用appt2的-stable-ids和-emit-ids兩個參數(shù)實現(xiàn)固化資源id的功能,并將將固化后的ids文件命名為shared_res_public.xml存儲在公共資源庫中,業(yè)務(wù)插件依賴公共資源庫,在打包編譯的過程中aura會將shared_res_public.xml復(fù)制到業(yè)務(wù)工程臨時編譯文件夾intermediates下的指定位置并參與業(yè)務(wù)模塊的打包過程中,其文件內(nèi)容格式如下:

修改R文件瘦身gradle plugin 代碼,從指定位置讀取并識別這部分公共資源,按照的形式進(jìn)行變量存儲,并在后續(xù)過程中對業(yè)務(wù)模塊中的公共資源部分進(jìn)行id替換。

public Map parse() throws Exception {        if (in == null) {            return null;        }        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();        DocumentBuilder builder = factory.newDocumentBuilder();        Document doc = builder.parse(in);        Element rootElement = doc.getDocumentElement();        NodeList list = rootElement.getChildNodes();        ......        return resNode;    }}

R類資源id內(nèi)聯(lián)部分代碼如下:

public void visitFieldInsn(int opcode, String owner, String name, String desc) {        if (opcode == Opcodes.GETSTATIC) {            //優(yōu)先從業(yè)務(wù)模塊R類資源中查找            Object value = jdRstore.getRFieldValue(owner, name);            if (value != null) {                mv.visitLdcInsn(value);                return;            }           //從公共R類資源中查找            value = getPublicRFileValue(name);            if (value != null) {                mv.visitLdcInsn(value);                return;            }        }        super.visitFieldInsn(opcode, owner, name, desc);    }

該方案完善后,結(jié)合商詳業(yè)務(wù)插件進(jìn)行了驗證,在商詳及宿主均完成R文件內(nèi)聯(lián)瘦身后,商詳模塊業(yè)務(wù)功能可正常使用,無異常現(xiàn)象。

考慮到R文件內(nèi)聯(lián)瘦身gradle plugin是在打包編譯階段引入的,我們也統(tǒng)計了一下引入該插件以后對打包時長的影響,數(shù)據(jù)如下:

結(jié)合數(shù)據(jù)來看,引入R文件瘦身插件后對整體打包時長并無顯著影響。

至此,基于京東商城探索的插件化工程R文件瘦身gradle plugin就開發(fā)完成,目前已在部分業(yè)務(wù)插件模塊進(jìn)行了線上驗證,在功能上線以后我們也及時的進(jìn)行了崩潰觀測以及用戶反饋的跟進(jìn),暫無異常問題。當(dāng)然圍繞R文件瘦身縮減包體積這個目的,開發(fā)人員有各種各樣的技術(shù)方案,上述方案不一定適用于所有的客戶端開發(fā)體系,另外后續(xù)也將圍繞包瘦身這一常態(tài)事務(wù)建設(shè)一系列的相關(guān)工具,介入工作當(dāng)中的各個階段,高效、有效的控制包體積的增長,如大家在瘦身方面有相關(guān)建議和想法也歡迎大家來一起討論。

參考文章:

Gradle Plugin:

https://docs.gradle.org/current/userguide/custom_plugins.html

Gradle Transform:

https://developer.android.com/reference/tools/gradle-api/7.0/com/android/build/api/transform/Transform

APK 構(gòu)建流程:

https://developer.android.com/studio/build/index.html?hl=zh-cn#build-process

作者:耿蕾 田創(chuàng)新

來源:京東云開發(fā)者社區(qū)

關(guān)鍵詞

上一篇:本草綱目秘方偏方大全減肥_本草綱目減肥配方 全球要聞 最后一頁下一篇:

推薦內(nèi)容
国产欧美日韩| 欧美性猛交xxxx富婆| 自拍视频亚洲| 欧美aaaa视频| 99热国内精品永久免费观看| 天天影视综合| 国产欧美日韩一区二区三区在线| 99在线热播精品免费99热| 午夜一级久久| 国产一区二区三区久久久| 成人av在线播放网址| 91麻豆swag| 亚洲精选在线视频| 欧美日韩一区二区三区| 欧美午夜电影网| 亚洲精品大尺度| 久久久久北条麻妃免费看| 91chinesevideo永久地址| 成人免费观看a| avtt亚洲| 电影在线观看一区二区| 国产精品黄网站| 午夜精品999| 精品在线视频一区| 国产欧美一区二区精品秋霞影院 | 欧美日韩一区二区三区不卡视频| xxxx日韩| 欧美a级一区| 国产精品资源在线| 最新国产成人在线观看| 91成人免费在线视频| 国产视频在线一区二区| 国产91av在线| 极品白浆推特女神在线观看| 麻豆福利在线观看| 天堂精品在线视频| 韩国欧美一区| 菠萝蜜视频在线观看一区| 欧美激情一区三区| 日韩欧美精品免费在线| 日韩精品在线播放| 国产成人激情视频| 91免费在线| 国产精品igao视频网网址不卡日韩| 在线视频亚洲专区| 日韩av在线发布| 中国av一区二区三区| 884aa四虎影成人精品一区| 另类少妇人与禽zozz0性伦| 免费av播放| 999福利在线视频| 久久av综合| 国产一区二区三区蝌蚪| 亚洲一区视频在线| 亚洲人成77777在线观看网| 国产精品久久久久久久7电影| 免费黄色在线网站| 欧美亚洲国产日韩| 国产一二三精品| 一本大道久久精品懂色aⅴ| y97精品国产97久久久久久| 午夜免费性福利| 国产亚洲一区二区手机在线观看| 五月婷婷六月综合| 国产免费观看久久| 亚洲国产日韩欧美在线动漫| 国产精品自产拍在线观| 牛牛精品一区二区| 黄色av日韩| 伊人一区二区三区| 久久国产天堂福利天堂| 成人午夜电影在线观看| 色综合www| 91丨九色丨蝌蚪丨老版| 日韩精品一区二区三区视频| 国产一区二中文字幕在线看| 欧美三区四区| 久久综合网络一区二区| 欧美日韩亚洲系列| 欧美一级高清免费| jizz内谢中国亚洲jizz| 国产在线欧美| 亚洲风情在线资源站| 久久视频在线视频| www视频在线免费观看| 午夜激情久久| 亚洲国产精品久久久久婷婷884 | www.国产精品.com| 精品在线91| 国产日韩欧美精品一区| 亚洲欧美国产精品久久久久久久 | 色综合久久久久久久久久久| 久久久久久久久久av| a级网站在线播放| 欧美黄色大片网站| 亚洲制服丝袜在线| 日本欧美中文字幕| 周于希免费高清在线观看| 欧美亚洲三级| 欧美日韩国产123区| 超碰在线首页| 欧美三级情趣内衣| 香蕉成人伊视频在线观看| 日本午夜精品理论片a级appf发布| 日韩国产激情| 成人激情视频网站| 久久天天躁狠狠躁夜夜躁| 超碰在线cao| 国产精品一区二区在线观看不卡| 亚洲第一二三四五区| 午夜精品一区| 久久婷婷亚洲| 日韩h在线观看| 色在线视频网| 国产在线国偷精品免费看| 亚洲精品日韩欧美| aa级大片免费在线观看| 精品一区二区三区影院在线午夜| 亚洲精品一区二区三区四区高清| av在线中文| 久久久久国产精品午夜一区| 日韩色在线观看| 成年人网站在线| 卡一卡二国产精品 | 久久久久北条麻妃免费看| 97在线视频免费观看完整版| 久久99精品一区二区三区三区| 亚洲成色www8888| 成入视频在线观看| 不卡视频免费播放| 韩国三级电影久久久久久| 精品一区二区三区亚洲| 中文字幕成人av| 国产精品视频一| 精品久久久久久久久久久下田| 亚洲综合偷拍欧美一区色| 成人福利免费观看| 综合av在线| 精品久久久三级丝袜| 欧美xxx黑人xxx水蜜桃| 国产成人丝袜美腿| 午夜精品在线视频| 亚洲自拍都市欧美小说| 色婷婷久久一区二区三区麻豆| 欧美色18zzzzxxxxx| 日本午夜精品一区二区三区电影| 国产亚洲xxx| 成人亚洲精品| 欧美性猛交xxxx| 人妖欧美1区| 国产欧美日韩亚州综合 | av免费在线视| 久久久夜色精品亚洲| 国产在线视频不卡| 欧美a级在线| 这里只有精品视频| 露出调教综合另类| 91精品国产福利在线观看 | 欧美aaa级| 亚洲午夜在线视频| 久久久久久久久免费视频| 国产呦萝稀缺另类资源| 97不卡在线视频| 欧美ab在线视频| 色哟哟亚洲精品一区二区| aaa国产精品| 日韩欧美激情在线| 成人在线免费电影网站| 婷婷中文字幕综合| 日本动漫理论片在线观看网站| 欧美国产一区二区| 黄色片免费在线| 91片在线免费观看| 在线免费91| 99精品在线观看视频| 五月伊人六月| 成人免费视频免费观看| 96久久久久久| 国产麻豆一精品一av一免费 | 国产精品视频最多的网站| 国产精品外国| 日本欧美在线视频| 日韩精品一二三四| 国产精品视频久久久久| 蜜桃91丨九色丨蝌蚪91桃色| 国产精品高潮粉嫩av| 秋霞午夜av一区二区三区| 国产精品免费福利| 国产麻豆9l精品三级站| 91美女在线| 久久精品亚洲精品国产欧美kt∨| 欧美日韩视频精品二区| 欧美激情一区二区三区在线| 日韩毛片久久久| 午夜精品成人在线| 电影中文字幕一区二区| 亚洲二区中文字幕| 91日韩欧美| 欧美中文字幕在线播放| 久久99精品国产.久久久久久|