美文网首页
Android减少App方法数

Android减少App方法数

作者: MarvinGuo | 来源:发表于2017-02-09 18:30 被阅读0次

    作为Android开发者我们都知道Android应用方法数65535这样一个限制,这是因为在Android系统中,方法的id使用short类型存储在Dex文件中,而short类型的取值范围是-32,768到32,767,因此导致Android应用方法数65535这样一个最大限制,超过这个方法是打包就会失败,也可以使用MultiDexApplication来解决,但这不是最优的解决方案,也可是用插件化来解决这个问题(稍后我会分享插件化),个人觉得最好是在开发中尽量避免这样的问题。

    1.为什么要减少方法数

    这要从dex的文件格式说起,在把源码编译、转化为dex文件格式时,dex文件中会有一个区域包含了所有源码中定义或引用的方法列表。这个区域中所有方法项的总数就是方法数。

    Android在刚开始被设计的时候,这一区域的方法数量不能超过65536个,也就是2个字节表示的范围。当源码定义或引用的方法数量超过了这个限制的话,就会导致编译不成功,你说重要不重要呢?

    2.如何查看这些方法?

    dexdump 命令:

    查看apk的method总数  dexdump  -f  app.apk | grepmethod_ids_size   

    查看apk的field总数dexdump  -f  app.apk | grepfield_ids_size

    查看apk的method详情  dexdump -f  app.apk

    可以使用修改过的dexdump。标准的dexdump可以解析方法列表,但无法打印出来,修改版的dexdump可以打印这些信息

    如下是一个简单类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.减少方法数的办法

    以下所介绍的方法都可以在修改后,用dexdump –j来观察、比较所修改的方法以及验证减少的效果。

    方法1 避免在内部类中访问外部类的私有方法/变量

    当在Java内部类(包括内部匿名类)中访问外部类的私有方法/变量时,编译器会生成额外的方法,这也会增加方法数,建议编码时尽量避免。

    具体原因:

    考虑如下的代码

    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语言允许内部类直接访问外部类的方法,但是虚拟机却认为Foo和Foo$Inner是两个不同的类,为了支持Foo$Inner访问Foo的private成员,编译器会生成两个额外的方法,而生成的这些方法也算在方法总数里面

    /*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

    解决办法:

    很简单,把mValue和doStuff()的private修饰符去掉就好了,这样它的默认访问域为包级,编译器就不需要生成额外的代码。

    方法2 避免调用派生类中的未被覆盖(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);

    }

    }

    }

    实际上它会生成5个方法,除了定义的onCreate和构造函数之外,还有setContentView、getIntent()和finish()。因为按照java的语义,如果有覆盖父类的方法,则会直接调用覆盖的方法。

    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

    解决办法:

    对于不需要被override的方法,显式的改成调用父类的方法,如下所示

    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);

    }

    }

    }

    则实际在方法数列表中它只占2个方法

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

    Method: ()V

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

    相关文章

      网友评论

          本文标题:Android减少App方法数

          本文链接:https://www.haomeiwen.com/subject/tirwittx.html