Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Android代码上减少方法数的一些奇技淫巧

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

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

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

一、工具介绍

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

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

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

(1)场景

先看一个简单的类:

代码语言:txt
AI代码解释
复制
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
AI代码解释
复制
public class MainActivity extends AppCompatActivity {

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

工具看下方法数:

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

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

(3) 其他特例

代码语言:txt
AI代码解释
复制
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
AI代码解释
复制
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
AI代码解释
复制
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 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
ORM查询语言(OQL)简介--高级篇(续):庐山真貌
相关文章内容索引: ORM查询语言(OQL)简介--概念篇 ORM查询语言(OQL)简介--实例篇 ORM查询语言(OQL)简介--高级篇:脱胎换骨 ORM查询语言(OQL)简介--高级篇(续):庐山真貌    PDF.NET框架的OQL经过“脱胎换骨”般的重构之后,引来了它华丽丽的新篇章,将“对象化的SQL”特征发挥到极致,与至于我在Q群里面说这应该算是OQL的“收山之作”了。然而,我这么说有什么依据?它的设计哲学是什么?它究竟是何样?由于本文篇幅较长,请听本篇慢慢道来,叙说它的庐山真面目! [有图有真相
用户1177503
2018/02/27
2.3K0
ORM查询语言(OQL)简介--高级篇(续):庐山真貌
.NET ORM 的 “SOD蜜”--零基础入门篇
PDF.NET SOD框架不仅仅是一个ORM,但是它的ORM功能是独具特色的,我在博客中已经多次介绍,但都是原理性的,可能不少初学的朋友还是觉得复杂,其实,SOD的ORM是很简单的。下面我们就采用流行的 Code First的方式,一步步来了解下。 一、准备工作 1.1,添加SOD包引用 首先建立一个控制台项目(支持.NET2.0的项目),并使用程序包管理器添加PDF.NET SOD的程序引用: PM> Install-Package PDF.NET.SOD 更多详细使用信息说明,请参考nuget 网站说明
用户1177503
2018/02/27
1.2K0
.NET ORM 的 “SOD蜜”--零基础入门篇
使用操作符重载,生成ORM实体类的SQL条件语句
ORM框架的一个不可或缺的功能就是根据实体类,生成操作数据库的SQL语句,这其中,最难处理的就是那些复杂的SQL条件比较语句。比如,有下面这样一个SQL语句: SELECT [id],[BankCode],[CityCode],[FundCode],[FundName],[FundReviews],[EndDagte],[addDate]  FROM [FundReviews]     WHERE  (               ([CityCode]=@CP1 OR [BankCode]=@CP2)  
用户1177503
2018/02/26
8180
左求值表达式,堆栈,调试陷阱与ORM查询语言的设计
1,表达式的求值顺序与堆栈结构 “表达式” 是程序语言一个很重要的术语,也是大家天天写的程序中很常见的东西,但是表达式的求值顺序一定是从左到右么? C/C++语言中没有明确规定表达式的运算顺序(从左到右,或是从右到左),这点与C#及Java语言都不同。不过可以确定的是,C#表达式的求值顺序一定是从左到右的。这个问题虽然对于大多数情况来说不重要,甚至很多普通C#,Java开发者都会忽略的问题,但是对于语言设计者,框架设计者,这是有可能需要考虑的问题。 堆栈是2种数据结构,“栈” 是一种后进先出的数据结构,也就
用户1177503
2018/02/27
8950
ORM查询语言(OQL)简介--高级篇:脱胎换骨
相关文章内容索引: ORM查询语言(OQL)简介--概念篇 ORM查询语言(OQL)简介--实例篇 ORM查询语言(OQL)简介--高级篇:脱胎换骨 ORM查询语言(OQL)简介--高级篇(续):庐山真貌     在写本文之前,一直在想文章的标题应怎么取。在写了《ORM查询语言(OQL)简介--概念篇》、《ORM查询语言(OQL)简介--实例篇》之后,觉得本篇文章应该是前2篇的延续,但又不是一般的延续,因为今天要写的这篇内容,是基于对框架OQL完全重构之后来写的,所以加上一个副标题:脱胎换骨! 一、OQL之
用户1177503
2018/02/27
2.7K0
ORM查询语言(OQL)简介--高级篇:脱胎换骨
打造轻量级的实体类数据容器
    这里有三个关键词:轻量级,实体类,数据容器,还有一个潜在的关键词:通用。这几个名词之间有什么联系呢?     一般来说,操作实体类往往伴随着一个实体类集合,而这些集合就是实体类的容器,在这里我将“容器”视作一个比集合更广泛的概念,例如Entity Framework做了一个重量级的容器ObjectContext,用于与作为对象(这些对象为 EDM 中定义的实体类型的实例)的数据进行交互。     实体类与容器没有必然关系,例如DataSet也是一个容器,它存储并操作DataTable,而DataTa
用户1177503
2018/02/26
7220
ORM查询语言(OQL)简介--概念篇
相关文章内容索引: ORM查询语言(OQL)简介--概念篇 ORM查询语言(OQL)简介--实例篇 ORM查询语言(OQL)简介--高级篇:脱胎换骨 ORM查询语言(OQL)简介--高级篇(续):庐山真貌 一、SQL与ORM   关系数据库(RDBMS)的查询有SQL(Structured Query Language)结构化查询语言,相比高级程序语言(命令式语言)而言,SQL主要描述想要做什么,而不是命令式语言的具体如何做,因此,SQL也被称为第四代语言(4GL),它为现代大多数的关系数据库系统所支持
用户1177503
2018/02/27
2.6K0
ORM查询语言(OQL)简介--概念篇
使用OQL“语言”构造ORM实体类的复杂查询条件
OQL”语言“ 是PDF.NET数据开发框架的实体对象查询语言,一直以来,ORM的复杂查询条件都是困扰ORM的问题,所以很多时候不得不舍弃ORM,直接手工拼接SQL。我们来看看OQL是怎么解决这些问题的,现在举一个今天同事遇到的问题: 有这样一个实体类 MyEntity,实体类的具体定义在此忽略,有兴趣的朋友请看我的博客。 MyEntity e=new MyEntity(); e.F1="1"; e.F2="2"; e.F3="a";//其它可选值 a,b,c..... e.F5="A";//其它可选值 A
用户1177503
2018/02/26
1.7K0
使用PDF.NET数据开发框架的实体操作语言OQL构造复杂查询条件
PDF.NET数据开发框架(Pwmis Data develop Framework,http://www.pwmis.com/sqlmap) 是一套借鉴iBatis、Hibernate、Linq等数据访问框架而来的轻量级数据开发框架,主要特点是具有iBatis特点的SQL-MAP功能和框架独特的实体对象查询语言--OQL,下面我们使用OQL来构造一个复杂的实体查询。 首先定义两个实体类:用户类和订单类,可以使用框架提供的实体类生成器生成,下面是详细代码: /*   本类由PWMIS 实体类生成工具(Ver
用户1177503
2018/02/26
1.7K0
PDF.NET数据开发框架操作MySQL实体类操作实例
在我们最近的项目中,SQL-MAP使用较多,但是实体类用的很少,实际上,“PDF.NET数据开发框架”的实体类相当强大,下面的测试程序是在MySQL中操作的实例。 1,首先在App.config文件中
用户1177503
2018/02/26
1K0
用事实说话,成熟的ORM性能不是瓶颈,灵活性不是问题:EF5.0、PDF.NET5.0、Dapper原理分析与测试手记
[本文篇幅较长,可以通过目录查看您感兴趣的内容,或者下载格式良好的PDF版本文件查看]  目录 一、ORM的"三国志"    2 1,PDF.NET诞生历程    2 2,Linq2Sql&EF:    3 3,微型ORM崛起    4 二、一决高下    4 2.1,ORM没有DataSet快?    4 2.1.1,ORM生成SQL的质量问题    4 2.1.2,DataReader没有DataSet快?    5 2,ORM的三个火枪手    6 2.1,委托+缓存    6 2.2,表达式树 
用户1177503
2018/02/27
4.2K0
用事实说话,成熟的ORM性能不是瓶颈,灵活性不是问题:EF5.0、PDF.NET5.0、Dapper原理分析与测试手记
PDF.NET数据开发框架实体类操作实例
本篇是 PDF.NET数据开发框架实体类操作实例(MySQL) 的姊妹篇,两者使用了同一个测试程序,不同的只是使用的类库和数据库不同,下面说说具体的使用过程。 1,首先在App.config文件中配置
用户1177503
2018/02/26
9990
PDF.NET数据开发框架实体类操作实例(for PostgreSQL,并且解决自增问题) PDF.NET数据开发框架实体类操作实例(MySQL)
本篇是 PDF.NET数据开发框架实体类操作实例(MySQL) 的姊妹篇,两者使用了同一个测试程序,不同的只是使用的类库和数据库不同,下面说说具体的使用过程。 1,首先在App.config文件中配置
用户1177503
2018/02/27
1.6K0
DataSet的灵活,实体类的方便,DTO的效率:SOD框架的数据容器,打造最适合DDD的ORM框架
引言:DDD的困惑 最近,我看到园子里面有位朋友的一篇博客 《领域驱动设计系列(一):为何要领域驱动设计? 》文章中有下面一段话,对DDD使用产生的疑问: •没有正确的使用ORM, 导致数据加载过多,导致系统性能很差。 •为了解决性能问题,就不加载一些导航属性,但是却把DB Entity返回上层,这样对象的一些属性为空,上层使用这个数据时根本不知道什么时间这个属性是有值的,这个是很丑陋的是不是? 博主说的第一个问题,是因为使用ORM的人把实体类的全部属性的数据查询出来了,相当于执行了 select * f
用户1177503
2018/02/27
2.7K0
DataSet的灵活,实体类的方便,DTO的效率:SOD框架的数据容器,打造最适合DDD的ORM框架
一行代码调用实现带字段选取+条件判断+排序+分页功能的增强ORM框架
问题:3行代码 PDF.NET 是一个开源的数据开发框架,它的特点是简单、轻量、快速,易上手,而且是一个注释完善的国产开发框架,受到不少朋友的欢迎,也在我们公司的项目中多次使用。但是,PDF.NET比起EF来,仍然有很大的劣势,主要就是用起来没有EF简单,这个问题饱受广大朋友的批评,但我很感谢这些朋友,他们的批评才是框架进步的动力,为此,之前我发表了《来一点反射和Emit,让ORM的使用极度简化》  这篇文章,使得不再需要定义实体类,只需要有接口即可访问数据库:     原文的代码:     static
用户1177503
2018/02/26
1.4K0
一行代码调用实现带字段选取+条件判断+排序+分页功能的增强ORM框架
Oracle 免费的数据库--Database 快捷版 11g 安装使用与"SOD框架"对Oracle的CodeFirst支持
一、Oracle XE 数据库与连接工具安装使用 Oracle数据库历来以价格昂贵出名,当然贵有贵的道理,成为一个Oracle DBA也是令人羡慕的事情,如果程序员熟悉Oracle使用也有机会接触到大型的项目,但是Oracle似乎对一般程序员不怎么友好,因为其繁琐的安装配置过程和对系统硬件的苛求,另一般人望而止步,我最早从Oracle 9i开始接触它,深有感受,特别是熟悉了SqlServer的开发人员,初次接触Oracle还是很不习惯的。比如它没有SqlServer数据“库”的概念,一个sa账号管理很多数据
用户1177503
2018/02/27
3K0
Oracle 免费的数据库--Database 快捷版 11g 安装使用与"SOD框架"对Oracle的CodeFirst支持
来一点反射和Emit,让ORM的使用极度简化
PDF.NET开发框架一直是号称“无需反射”的,因为它的ORM框架(PDF.NET不仅仅是一个ORM框架,详细请见官网)中实体类的设计很特别,不需要反射就能够获知映射的字段信息,我们用实际的例子来说明
用户1177503
2018/02/27
1K0
来一点反射和Emit,让ORM的使用极度简化
实体类的枚举属性--原来支持枚举类型这么简单,没有EF5.0也可以
    通常,我们都是在业务层和界面层使用枚举类型,这能够为我们编程带来便利,但在数据访问层,不使用枚举类型,因为很多数据库都不支持,比如我们现在用的SqlServer2008就不支持枚举类型的列,用的时候也是将枚举类型转换成int 类型,数据库存储的是int 类型的数据,在访问数据的时候进行枚举类型和int类型的转换,例如下面的例子: public enum RoleNames { User, Manager, Admin } 假设
用户1177503
2018/02/26
1.8K0
实体类的枚举属性--原来支持枚举类型这么简单,没有EF5.0也可以
如何用ORM支持SQL语句的CASE WHEN?
OQL如何支持CASE WHEN? 今天,一个朋友问我,OQL可否支持CASE WHEN语句?他给的示例SQL如下: select HName,case when IsEnable=1 then '启用' else '停用' from tb_User OQL是SOD框架的ORM查询语言,它类似Linq,但是它诞生的历史比Linq早,并且更加接近SQL语法。所以,对SOD框架而言,对应ORM如何支持CASE WHEN,就等于是问OQL如何支持CASE WHEN了。 这个问题已经不止这一个朋友来问我了,我想了下
用户1177503
2018/02/26
2.2K0
不使用反射,“一行代码”实现Web、WinForm窗体表单数据的填充、收集、清除,和到数据库的CRUD
问题篇:     昨天在CSDN看到这样一个帖子:“苦逼的三层代码”: 采用传统的三层架构写代码,每个数据表都要定义一个实体对象,编写后台的时候, Web层需要针对页面的用户输入逐个手动编写赋值到实体对象的各个属性,然后DAL层还要用SqlHelper 进行各个存储过程对应参数的实体赋值, 我的天呀,写几个表还好,多个表呢, 写的后台都没力气, 典型的苦逼代码工没营养,各位有啥好的处理方法或开发方式。。     看到跟帖,大部分都说使用ORM解决这个问题,但我觉得ORM还是没有解决贴主的几个问题: 每个
用户1177503
2018/02/27
2.8K0
不使用反射,“一行代码”实现Web、WinForm窗体表单数据的填充、收集、清除,和到数据库的CRUD
推荐阅读
ORM查询语言(OQL)简介--高级篇(续):庐山真貌
2.3K0
.NET ORM 的 “SOD蜜”--零基础入门篇
1.2K0
使用操作符重载,生成ORM实体类的SQL条件语句
8180
左求值表达式,堆栈,调试陷阱与ORM查询语言的设计
8950
ORM查询语言(OQL)简介--高级篇:脱胎换骨
2.7K0
打造轻量级的实体类数据容器
7220
ORM查询语言(OQL)简介--概念篇
2.6K0
使用OQL“语言”构造ORM实体类的复杂查询条件
1.7K0
使用PDF.NET数据开发框架的实体操作语言OQL构造复杂查询条件
1.7K0
PDF.NET数据开发框架操作MySQL实体类操作实例
1K0
用事实说话,成熟的ORM性能不是瓶颈,灵活性不是问题:EF5.0、PDF.NET5.0、Dapper原理分析与测试手记
4.2K0
PDF.NET数据开发框架实体类操作实例
9990
PDF.NET数据开发框架实体类操作实例(for PostgreSQL,并且解决自增问题) PDF.NET数据开发框架实体类操作实例(MySQL)
1.6K0
DataSet的灵活,实体类的方便,DTO的效率:SOD框架的数据容器,打造最适合DDD的ORM框架
2.7K0
一行代码调用实现带字段选取+条件判断+排序+分页功能的增强ORM框架
1.4K0
Oracle 免费的数据库--Database 快捷版 11g 安装使用与"SOD框架"对Oracle的CodeFirst支持
3K0
来一点反射和Emit,让ORM的使用极度简化
1K0
实体类的枚举属性--原来支持枚举类型这么简单,没有EF5.0也可以
1.8K0
如何用ORM支持SQL语句的CASE WHEN?
2.2K0
不使用反射,“一行代码”实现Web、WinForm窗体表单数据的填充、收集、清除,和到数据库的CRUD
2.8K0
相关推荐
ORM查询语言(OQL)简介--高级篇(续):庐山真貌
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档