前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android代码上减少方法数的一些奇技淫巧

Android代码上减少方法数的一些奇技淫巧

原创
作者头像
Clayman Twinkle
发布2018-07-25 09:44:19
8560
发布2018-07-25 09:44:19
举报
文章被收录于专栏:Android原创

随着Android项目代码量的增加,当应用方法数量超过了65536的时候,编包的时候就会报出著名“64k”方法数问题。虽然然最简单粗暴的方法是分dex,还有其他像混淆等,但本人还是研究了几种代码上减少方法的方式,希望能帮到“有缘人”。

一、工具介绍

二、代码场景与方法数分析

下面要介绍下几种常见的代码使用场景,分析方法数增加情况。

1.1 子类中调用了父类中未被子类重写的方法

(1)场景

先看一个简单的类:

代码语言:txt
复制
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

按照我们手算出来的方法数是2(一个默认构造器,一个onCreate方法);

那我们使用工具看下这个类的方法数。

MainActivity的方法数
MainActivity的方法数
MainActivity.smali文件
MainActivity.smali文件

3个?为什么是3个?原来是多了setContentView这个方法。因为按照java的语义,如果有覆盖父类的方法,则会直接调用覆盖的方法。从smali文件可以看出setContentView是属于MainActivity的方法。

(2)解决方案

那这次我们改成这样:

代码语言:txt
复制
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.activity_main);
    }
}

工具看下方法数:

修改后MainActivity的方法数
修改后MainActivity的方法数

结果的确和我们手算出来的一样!

(3) 其他特例

代码语言:txt
复制
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.activity_main);
    }
}

public class TestActivity extends MainActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.activity_main);
    }
}
MainActivity和TestActivity的方法数
MainActivity和TestActivity的方法数
TestActivity.smali文件
TestActivity.smali文件

方法数实际增加了5个。因为TestActivitysuper就是MainActivity,而MainActivity并没有setContentView这个方法,而AppCompatActivity才有,所以这时候的super.setContentView相当于this.setContentView

这个其实也是有解决办法的,可以这样写((AppCompatActivity)this).setContentView

(4)综上所述:

子类中调用了父类中未被子类重写的方法时,请尽量使用super来调用或者使用方法的父类强转下this

1.2 私有内部类

(1)场景

代码语言:txt
复制
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.activity_main);
        new Thread(new Task()).start();
    }

   private class Task implements Runnable{

        @Override
        public void run() {
        }
    }
}

目测,MainActivity2个方法数(默认构造器、onCreate),Task2个方法数(默认构造器、run)。

那,事实是不是这样呢?

工具看下方法数:

MainActivity和Task方法数
MainActivity和Task方法数
MainActivity$Task.smali文件
MainActivity$Task.smali文件

MainActivity方法数没错,而Task实际上得出来的方法数却是3个。私有内部类默认直接增加了两个带参构造器。

其他情况呢?

(2)解决方案

实验了下非私有的内部类,是正常的,2个方法数。所以将内部类改成非private就能解决。

(3)综上所述:

建议定义内部类是尽量使用非私有的。

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

(1)场景

代码语言:txt
复制
public class MainActivity extends AppCompatActivity {

    private String text = "在内部类里调用";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.activity_main);
        new Thread(new Task()).start();
    }

   class Task implements Runnable{

        @Override
        public void run() {
            System.out.println(text);
        }
    }
}

1.2分析,目测是:MainActivity2个方法数(默认构造器、onCreate),Task2个方法数(默认构造器、run)。

而实际上,是:

MainActivity和Task方法数
MainActivity和Task方法数
MainActivity.smali文件
MainActivity.smali文件

在外部类中,增加了一个access$000的方法,这方法是为了支持Task访问MainActivityprivate变量。

若将字段变成非私有,就不会产生access$000的方法。

(2)综上所述:

若外部类字段有可能被内部类访问到,就尽量不使用private

三、总结

(1)子类中调用了父类中未被子类重写的方法时,请尽量使用super来调用。

(2)建议定义内部类是尽量使用非私有的。

(3)若外部类字段有可能被内部类访问到,就尽量不使用private

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、工具介绍
  • 二、代码场景与方法数分析
    • 1.1 子类中调用了父类中未被子类重写的方法
      • (1)场景
      • (2)解决方案
      • (3) 其他特例
      • (4)综上所述:
    • 1.2 私有内部类
      • (1)场景
      • (2)解决方案
      • (3)综上所述:
    • 1.3 在内部类中访问外部类的私有方法/变量
      • (1)场景
      • (2)综上所述:
  • 三、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档