随着Android项目代码量的增加,当应用方法数量超过了65536的时候,编包的时候就会报出著名“64k”方法数问题。虽然然最简单粗暴的方法是分dex,还有其他像混淆等,但本人还是研究了几种代码上减少方法的方式,希望能帮到“有缘人”。
下面要介绍下几种常见的代码使用场景,分析方法数增加情况。
先看一个简单的类:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
按照我们手算出来的方法数是2
(一个默认构造器,一个onCreate方法);
那我们使用工具看下这个类的方法数。
3个?为什么是3个?原来是多了setContentView
这个方法。因为按照java的语义,如果有覆盖父类的方法,则会直接调用覆盖的方法。从smali
文件可以看出setContentView
是属于MainActivity
的方法。
那这次我们改成这样:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_main);
}
}
工具看下方法数:
结果的确和我们手算出来的一样!
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);
}
}
方法数实际增加了5个。因为TestActivity
的super
就是MainActivity
,而MainActivity
并没有setContentView
这个方法,而AppCompatActivity
才有,所以这时候的super.setContentView
相当于this.setContentView
。
这个其实也是有解决办法的,可以这样写((AppCompatActivity)this).setContentView
。
子类中调用了父类中未被子类重写的方法时,请尽量使用super
来调用或者使用方法的父类强转下this
。
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() {
}
}
}
目测,MainActivity
2个方法数(默认构造器、onCreate
),Task
2个方法数(默认构造器、run
)。
那,事实是不是这样呢?
工具看下方法数:
MainActivity
方法数没错,而Task
实际上得出来的方法数却是3个。私有内部类默认直接增加了两个带参构造器。
其他情况呢?
实验了下非私有的内部类,是正常的,2个方法数。所以将内部类改成非private
就能解决。
建议定义内部类是尽量使用非私有的。
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
分析,目测是:MainActivity
2个方法数(默认构造器、onCreate
),Task
2个方法数(默认构造器、run
)。
而实际上,是:
在外部类中,增加了一个access$000
的方法,这方法是为了支持Task
访问MainActivity
的private
变量。
若将字段变成非私有,就不会产生access$000
的方法。
若外部类字段有可能被内部类访问到,就尽量不使用private
。
(1)子类中调用了父类中未被子类重写的方法时,请尽量使用super
来调用。
(2)建议定义内部类是尽量使用非私有的。
(3)若外部类字段有可能被内部类访问到,就尽量不使用private
。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有