前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开发减少方法数的建议 博客分类: Android小技巧 方法数android

Android开发减少方法数的建议 博客分类: Android小技巧 方法数android

作者头像
chroya
发布2018-10-31 17:51:59
4830
发布2018-10-31 17:51:59
举报
文章被收录于专栏:封碎封碎

     现在的Android应用越来越庞大,开发者越来越能感受到方法数限制带来的影响。这里简单讲几个减少方法数的小建议。

1.什么是方法数?为什么它这么重要?

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

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

2.如何查看这些方法?

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

如下是一个简单类LogicActivity中使用的方法

Class: Lcom/xxx/activity/LogicActivity; 18

Method: <init> ()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内部类(包括内部匿名类)中访问外部类的私有方法/变量时,编译器会生成额外的方法,这也会增加方法数,建议编码时尽量避免。

具体原因:

考虑如下的代码

代码语言:javascript
复制
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成员,编译器会生成两个额外的方法,而生成的这些方法也算在方法总数里面

代码语言:javascript
复制
/*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)的方法

考虑下面的代码

代码语言:javascript
复制
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: <init> ()V

Method: finish ()V

Method: getIntent ()Landroid/content/Intent;

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

Method: setContentView (I)V

解决办法:

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

代码语言:javascript
复制
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: <init> ()V

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

其实减少方法数还有很多办法,比如插件化之类的,后面有空再介绍。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015-11-04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档