作为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开发方法数,Android减少App方法数相关推荐

  1. Android 使用android-support-multidex解决Dex超出方法数的限制问题,让你的应用不再爆棚

    时之沙: http://blog.csdn.net/t12x3456 随着应用不断迭代,业务线的扩展,应用越来越大(比如集成了各种第三方sdk或者公共支持的jar包,项目耦合性高,重复作用的类越来越多 ...

  2. com.android.support:multidex,Android 使用android-support-multidex解决Dex超出方法数的限制问题...

    随着应用不断迭代,业务线的扩展,应用越来越大(比如集成了各种第三方sdk或者公共支持的jar包,项目耦合性高,重复作用的类越来越多),相信很多人都遇到过如下的错误: UNEXPECTED TOP-LE ...

  3. Android开发笔记(一百七十九)避免方法数过多的问题

    一个大规模的App工程,往往引入了数量繁多的第三方开发库,其中既有官方的Jetpack库,也有第三方厂商的开源包.有时候运行这种App会报错"Cannot fit requested cla ...

  4. android开发方法数,Android方法数methods超过65536详解

    当Android App中的方法数超过65535时,如果往下兼容到低版本设备时,就会报编译错误:Cannot fit requested classes in a single dex file. T ...

  5. 简述Android 解决65536/64K方法数限制方案

    在Android项目开发中,尤其是开发类似淘宝,京东,微信,直播等大型项目中,由于产品的迭代,业务模块的快速增长,到了一定的规模后难免会遇到65536/64K方法数的问题. 它是个什么鬼? 这个问题, ...

  6. 【Android 安全】DEX 加密 ( 多 DEX 加载 | 65535 方法数限制和 MultiDex 配置 | PathClassLoader 类加载源码分析 | DexPathList )

    文章目录 一.65535 方法数限制和 MultiDex 配置 二.多 DEX 加载引入 三.PathClassLoader 类加载源码分析 四.BaseDexClassLoader 类加载源码分析 ...

  7. [Android] Android统计Apk , jar包方法数

    reference to : http://www.jianshu.com/p/61e8f803e0d1 Android在开发过程中,随着引用的库以及业务的增多,不可避免的会出现64K limit问题 ...

  8. 方法超出 android,Android工程方法数超过64k,The number of method references in a .dex file cannot exceed 64K....

    最近将一个老的Eclipse项目转到Android Studio后,用gradle添加了几个依赖,项目可以make,但是一旦run就报错 Error:The number of method refe ...

  9. android studio升级到3.0之后布局视图_升级到AndroidStudio3.0 之后的遇到问题的处理(新建、方法数限制等)...

    引言: 遇到的新问题: 1,新建项目报错: Unable to resolve dependency for :app@debug/compileClasspath': Could not resol ...

最新文章

  1. 陆奇首批YC中国门徒:包鱼塘、画动漫、搞汽配…都用AI
  2. ubuntu python3.8安装pip_ubuntu16.04纯净版-安装Python3.8.1/升级pip
  3. [***]HZOJ 跳房子
  4. 使用Fabric8在CDI管理的bean中注入Kubernetes Services
  5. hive metastore mysql_Hive MetaStore的结构
  6. android手机浏览器研究报告,QQ浏览器Android客户端产品体验报告
  7. SQLite中利用事务处理优化DB操作
  8. svmlib java_Libsvm Java
  9. UEditor(四)——表情包
  10. open source Lrc歌词解析器发布
  11. exmail邮件被退回
  12. matlab2c使用c++实现matlab函数系列教程-imag函数
  13. ar8161网卡 linux,解决AR8161网卡驱动的方法
  14. 形如e^(ax^2+bx+c)的积分公式的证明
  15. w10计算机无法打印,win10提示“无法打印 似乎未安装打印机”怎么办
  16. OGS标准以及常见的标准服务
  17. 地图与WebGIS、地图的作用、数字地图的应用
  18. Solidworks异型孔打孔失败原因分析
  19. 〖全域运营实战白宝书 - 运营角色认知篇①〗- 初识运营,明晰运营的学习路径
  20. 全球及中国浮区硅晶圆行业发展格局分析及投资前景调研报告2022-2028年

热门文章

  1. 【初涉C语言】程序员欢迎来到C语言的世界!
  2. java url 本地文件是否存在_我的应用程序知道URL中是否存在文件会一直停止[重复]...
  3. mysql 备份 一张表_mysql 备份表的一个方法
  4. php百度坐标转腾讯坐标,PHP腾讯与百度坐标转换
  5. Python 命令行传参
  6. RNN,LSTM,GRU的理解
  7. UVA - 1368 ​​​​​​​DNA Consensus String
  8. Node操作Mysql的简单例子
  9. Exchange队列优先级介绍和配置
  10. vscode Go 1.11.4 编译错误 need Delve built by Go 1.11 or later