开机速度
- splash广告逻辑,首次加载的图片为应用放在res文件夹下面几个文件夹里面的图片,同时会去调用接口获取下一次打开的时候要显示的图片url,并缓存图片;下次进入该界面显示图片并继续访问接下来一次的图片,为了保证打开速度,这个网络请求务必异步处理。
- 引导图,不要超过4页。动画可原生实现,可gif,可视频来实现。
- 进入首页之前进行地理位置的定位,保证进入首页显示的数据为当前城市的信息。
- app首页设计,尽可能多的将所有产品展示在首页,会有广告,搜索栏,滚动条。
上面为用户可见的数据,一些不可见数据:
- umeng打点,统计激活数。
- 注册推送。
- 根据推送协议进行页面跳转。
- 初始化崩溃收集机制,比如崩溃信息上传等。
为了加快splash的加载速度建议客户端这边尽可能避免耗时间的任务操作
html5页面打开速度
- 将html5数据打包进zip包里面去,每次从本地zip解压文件里面加载html5数据;新增或者修改html5信息怎么办,进行版本控制,如果版本一致,加载本地解压数据,如果不是加载新的zip包的解压数据;其中公共的,不变化的html5数据压缩为公用的zip压缩包并下发,那么每次下载的时候只下载新增和修改的那部分html5文件的压缩包。在上个页面设置不可显示的webview加载html5数据,在下个webview加载的时候直接从本地缓存文件里面去加载。
安装包大小
- app安装包一定要小,或者实现增量更新,减少对用户流量的不必要耗费。
- 图片,音频,视频文件应该在前期提供的时候就尽可能处理的体积足够小。
我的观点:
对于分享,推送,定位,地图等第三方服务集成的时候,能用微信官方,新浪官方自己去实现就尽可能自己去实现,因为团队里面有人为了实现分享集成umeng分享功能,导致应用大小增加4M知道,其中包括很多无用的代码和资源文件,请慎重。
png和jpg的使用场景
- 同背景图片,png加载速度大于jpg,手机会对png进行硬件加速。
- 网络图片采用jpg图片比较合适。
- 广告图,引导图采用jpg比较合适。
splash图片,引导图,背景图
- splash图片现在在300-500k之间。
- 引导图可以将背景图片和前景图片分开,实现背景图片或者前景图片的可重用性。
- 背景图限制在1M以内,并没必要png格式,jpg格式就行了。
表情包的方案同上面html5页面打开速度的论述,都是通过zip来进行增量更新。
清理无用代码和资源文件
- eclipse时代用undector可以实现无用代码的检测,android studio暂时没发现,无用资源文件可以通过link来实现无用资源文件,无用style等检测,但是还是需要手动进行删除。
- 通过使用proguard来配置混淆代码文件来清理无用的代码,减少apk的大小。
性能优化
- 网络请求优化:针对2G,3G,4G,wifi环境服务器端配置不同的服务器,分别接入移动,联通,电信的专线,并在客户端进行配置,app登录获取遍历访问2G,3G,4G,wifi的针对性域名并判断出最佳的访问素的的域名,并在一段时间内访问该域名。为了避免抢占同一服务器的资源,可以在服务器端设置针对的优先级。
- 抛弃使用http+json,转而使用tcp+protobuf。
页面跳转逻辑解耦
我个人项目里面是写个路由类,所有的跳转逻辑都写在这个路由类里面,作为所有activity界面跳转中间控制层。
作者利用反射也提供了一个不错的思路:
import android.app.Activity; import android.content.Intent; public abstract class BaseActivity extends Activity { public void navigateTo(final String activityName, final Intent intent) { //在这个位置执行页面打点的操作,这里可以利用到activityName Class<?> clazz = null; try { clazz = Class.forName(activityName); if (clazz != null) { intent.setClass(this, clazz); this.startActivity(intent); } } catch (final ClassNotFoundException e) { return; } } }
activity的常量类:
public class ActivityNameConstants { public final static String SecondActivity = "com.example.navigator.SecondActivity"; }
demo:
import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.widget.Button; public class MainActivity extends BaseActivity { Button btnNav1, btnNav2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnNav1 = (Button) findViewById(R.id.btnNav1); btnNav1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, SecondActivity.class); startActivity(intent); } }); btnNav2 = (Button) findViewById(R.id.btnNav2); btnNav2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); intent.putExtra("name", "Jianqiang"); navigateTo(ActivityNameConstants.SecondActivity, intent); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
个人认为各有优缺点,还是看自己的偏好吧。
打点统计
页面打点:放在跳转逻辑代码前面;
事件打点:打点逻辑写在基类控件里面,比如写onclick等触发事件的基类,并在这些基类里面写事件打点的逻辑。
多渠道打包
我一般是上传到360,百度等加固平台惊醒加固打包,然后利用平台的多渠道打包工具进行批量多渠道打包,书里面讲的是python程序来实现,你可以去github找找,这类代码很多。
class.dex的拆与合
主要还是处理65536的问题,2种方案:
- 插件化:独立模块做成单独的apk,使用dexClassLoader来进行加载。
- dex分包:主要利用multidex来实现class.dex的拆分。
模块化拆分
android代码的模块化拆分:
- 将常用的工具类代码,封装代码,第三方代码单独封装为基础类库。
- 指定资源文件命名规范,并以模块名称作为前缀来进行命名。
- 模块间传递的数据以json或者单独拉出来公用的bean作为一个库引用。
版本策略:
一般情况下版本名称为3位:比如6.0.0
第一位为大版本更新,第二位用于小版本迭代,第三位作为紧急发版。