Android減少App方法數(shù)

作為Android開(kāi)發(fā)者我們都知道Android應(yīng)用方法數(shù)65535這樣一個(gè)限制划乖,這是因?yàn)樵贏ndroid系統(tǒng)中,方法的id使用short類(lèi)型存儲(chǔ)在Dex文件中,而short類(lèi)型的取值范圍是-32,768到32,767梦碗,因此導(dǎo)致Android應(yīng)用方法數(shù)65535這樣一個(gè)最大限制,超過(guò)這個(gè)方法是打包就會(huì)失敗闸度,也可以使用MultiDexApplication來(lái)解決,但這不是最優(yōu)的解決方案蚜印,也可是用插件化來(lái)解決這個(gè)問(wèn)題(稍后我會(huì)分享插件化)莺禁,個(gè)人覺(jué)得最好是在開(kāi)發(fā)中盡量避免這樣的問(wèn)題。

1.為什么要減少方法數(shù)

這要從dex的文件格式說(shuō)起窄赋,在把源碼編譯哟冬、轉(zhuǎn)化為dex文件格式時(shí),dex文件中會(huì)有一個(gè)區(qū)域包含了所有源碼中定義或引用的方法列表寝凌。這個(gè)區(qū)域中所有方法項(xiàng)的總數(shù)就是方法數(shù)柒傻。

Android在剛開(kāi)始被設(shè)計(jì)的時(shí)候,這一區(qū)域的方法數(shù)量不能超過(guò)65536個(gè)较木,也就是2個(gè)字節(jié)表示的范圍。當(dāng)源碼定義或引用的方法數(shù)量超過(guò)了這個(gè)限制的話青柄,就會(huì)導(dǎo)致編譯不成功伐债,你說(shuō)重要不重要呢预侯?

2.如何查看這些方法?

dexdump 命令:

查看apk的method總數(shù) ?dexdump ?-f ?app.apk | grepmethod_ids_size ??

查看apk的field總數(shù)dexdump ?-f ?app.apk | grepfield_ids_size

查看apk的method詳情 ?dexdump -f ?app.apk


可以使用修改過(guò)的dexdump峰锁。標(biāo)準(zhǔn)的dexdump可以解析方法列表萎馅,但無(wú)法打印出來(lái),修改版的dexdump可以打印這些信息

如下是一個(gè)簡(jiǎn)單類(lèi)LogicActivity中使用的方法

Class: Lcom/xxx/activity/LogicActivity; 18

Method: ()V

Method: access$000 (Lcom/xxx/activity/LogicActivity;)Lcom/xxx/app/AppInterface;

Method: access$100 (Lcom/xxx/activity/LogicActivity;)Lcom/xxx/app/AppInterface;

Method: addFriend (Ljava/lang/String;ILjava/lang/String;)V

Method: addObserver (Lcom/xxx/app/BusinessObserver;)V

Method: finish ()V

Method: getIntent ()Landroid/content/Intent;

Method: getString (I)Ljava/lang/String;

Method: getTitleBarHeight ()I

Method: joinTroop ()V

Method: onActivityResult (IILandroid/content/Intent;)V

Method: onCreate (Landroid/os/Bundle;)V

Method: onDestroy ()V

Method: removeObserver (Lcom/xxx/app/BusinessObserver;)V

Method: setLastActivityName ()Ljava/lang/String;

Method: setResult (ILandroid/content/Intent;)V

Method: startActivity (Landroid/content/Intent;)V

Method: startActivityForResult (Landroid/content/Intent;I)V

可以看出虹蒋,這里面的方法是包含代碼中引用的方法的糜芳,如finish(),getIntent()這些方法魄衅。

3.減少方法數(shù)的辦法

以下所介紹的方法都可以在修改后峭竣,用dexdump –j來(lái)觀察、比較所修改的方法以及驗(yàn)證減少的效果晃虫。

方法1 避免在內(nèi)部類(lèi)中訪問(wèn)外部類(lèi)的私有方法/變量

當(dāng)在Java內(nèi)部類(lèi)(包括內(nèi)部匿名類(lèi))中訪問(wèn)外部類(lèi)的私有方法/變量時(shí)皆撩,編譯器會(huì)生成額外的方法,這也會(huì)增加方法數(shù)哲银,建議編碼時(shí)盡量避免扛吞。

具體原因:

考慮如下的代碼

publicclassFoo{

privateclassInner{

void stuff(){

Foo.this.doStuff(Foo.this.mValue);

}

}

privateint mValue;

publicvoid run(){

Innerin=newInner();

mValue =27;

in.stuff();

}

privatevoid doStuff(int value){

System.out.println("Value is "+ value);

}

}

雖然Java語(yǔ)言允許內(nèi)部類(lèi)直接訪問(wèn)外部類(lèi)的方法,但是虛擬機(jī)卻認(rèn)為Foo和Foo$Inner是兩個(gè)不同的類(lèi)荆责,為了支持Foo$Inner訪問(wèn)Foo的private成員滥比,編譯器會(huì)生成兩個(gè)額外的方法,而生成的這些方法也算在方法總數(shù)里面

/*package*/staticintFoo.access$100(Foo foo){

return foo.mValue;

}

/*package*/staticvoidFoo.access$200(Foo foo,int value){

foo.doStuff(value);

}

具體可以參考:http://developer.android.com/training/articles/perf-tips.html#PackageInner

解決辦法:

很簡(jiǎn)單做院,把mValue和doStuff()的private修飾符去掉就好了盲泛,這樣它的默認(rèn)訪問(wèn)域?yàn)榘?jí),編譯器就不需要生成額外的代碼山憨。

方法2 避免調(diào)用派生類(lèi)中的未被覆蓋(override)的方法

考慮下面的代碼

publicclass DemoActivity extends Activity {

@Override

protectedvoid onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

Intent intent = getIntent();

if (intent.getAction().equals("add")) {

finish();

}

else {

setContentView(R.id.background);

}

}

}

實(shí)際上它會(huì)生成5個(gè)方法查乒,除了定義的onCreate和構(gòu)造函數(shù)之外,還有setContentView郁竟、getIntent()和finish()玛迄。因?yàn)榘凑誮ava的語(yǔ)義,如果有覆蓋父類(lèi)的方法棚亩,則會(huì)直接調(diào)用覆蓋的方法蓖议。

Class: Lcom/xxx/activity/DemoActivity; 5

Method: ()V

Method: finish ()V

Method: getIntent ()Landroid/content/Intent;

Method: onCreate (Landroid/os/Bundle;)V

Method: setContentView (I)V

解決辦法:

對(duì)于不需要被override的方法,顯式的改成調(diào)用父類(lèi)的方法讥蟆,如下所示

publicclass DemoActivity extends Activity {

@Override

protectedvoid onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

Intent intent = super.getIntent();

if (intent.getAction().equals("add")) {

super.finish();

}

else {

super.setContentView(R.id.background);

}

}

}

則實(shí)際在方法數(shù)列表中它只占2個(gè)方法

Class: Lcom/tencent/mobileqq/activity/DemoActivity; 2

Method: ()V

Method: onCreate (Landroid/os/Bundle;)V

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末勒虾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子瘸彤,更是在濱河造成了極大的恐慌修然,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異愕宋,居然都是意外死亡玻靡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)中贝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)囤捻,“玉大人,你說(shuō)我怎么就攤上這事邻寿⌒粒” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵绣否,是天一觀的道長(zhǎng)誊涯。 經(jīng)常有香客問(wèn)我,道長(zhǎng)枝秤,這世上最難降的妖魔是什么醋拧? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮淀弹,結(jié)果婚禮上丹壕,老公的妹妹穿的比我還像新娘。我一直安慰自己薇溃,他們只是感情好菌赖,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著沐序,像睡著了一般琉用。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上策幼,一...
    開(kāi)封第一講書(shū)人閱讀 49,079評(píng)論 1 285
  • 那天邑时,我揣著相機(jī)與錄音,去河邊找鬼特姐。 笑死晶丘,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的唐含。 我是一名探鬼主播浅浮,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼捷枯!你這毒婦竟也來(lái)了滚秩?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤淮捆,失蹤者是張志新(化名)和其女友劉穎郁油,沒(méi)想到半個(gè)月后本股,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡已艰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年痊末,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蚕苇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哩掺。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖涩笤,靈堂內(nèi)的尸體忽然破棺而出嚼吞,到底是詐尸還是另有隱情,我是刑警寧澤蹬碧,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布舱禽,位于F島的核電站,受9級(jí)特大地震影響恩沽,放射性物質(zhì)發(fā)生泄漏誊稚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一罗心、第九天 我趴在偏房一處隱蔽的房頂上張望里伯。 院中可真熱鬧,春花似錦渤闷、人聲如沸疾瓮。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)狼电。三九已至,卻和暖如春弦蹂,著一層夾襖步出監(jiān)牢的瞬間肩碟,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工凸椿, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留削祈,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓削饵,卻偏偏與公主長(zhǎng)得像岩瘦,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子窿撬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容