版权声明:本文为博主原创文章,转载请注明出处!谢谢! https://blog.csdn.net/aaa1050070637/article/details/85115515
目录
基本组件
- Activity之间数据通信,当数据量较大时,避免采用Intent+Parcelable的方式,可以考虑EventBus等替代方案,避免造成TransactionTooLargeException;
- Activity隐式,在发出Intent跳转之前,需要对Activity进行ResolveActivity检查,以免造成ClassNotFoundException; 代码示例:if(getPackageManager.resolveActivity(intent,PackageManager.MATCH_DEFAULT_ONLY)!=NULL)
- 避免在Service#onstartCommand()以及OnBind()方法中执行耗时操作,如的确有需求,可以用IntentService或者其他异步机制来完成;
- 避免在BroadCastReceiver的onReceive()方法中执行耗时操作,有需求同上,可以采用IntentService完成,不能在方法体内直接new Thread()来完成;
- 对于只运用于应用内的BroadCastReceiver,尽量使用LocalBroadCastManager进行注册和发送,原因是安全性更好,并且具有更高的运行效率;
- 当前Activity中的onPause方法会执行完毕后,才会执行下一个Activity的onCreate()方法,所以避免在onPasue方法中执行时间较长的操作,影响跳转效率;
- 不要再Android中的Application中缓存数据,组件间的数据通讯,尽量使用Intent机制,也可以使用sharePreference来使数据持久化;
- Activity与Fragment中动态注册广播时,一定要注意register与unRegister要成对出现;
UI布局
- 布局中不得不使用ViewGroup多层嵌套时,尽量不要用LinearLayout,使用RelativeLayout可以有效降低嵌套层级;
- 在Activity中使用对话框、弹出浮层时,尽量用DialogFragment,而不是Dialog/AlertDialog,这样可以使Activity方便对对话框/弹出浮层进行生命周期管理;
- 禁止在非UI现场进行View操作;
- 禁止在设计布局时,多次对子Viewh和父View进行同样背景的设置,避免多次绘制,建议及时隐藏不需要显示的布局;
- 灵活使用布局,建议用Merge标签、ViewStub来优化布局,尽可能少的减少嵌套层级,推荐使用FrameLayout、LinearLayout、RelativeLayout次之;
进程、线程、消息通讯
- 不要通过Intent在Android基础组件中传递大数据(binder transaction中的缓存为1M),避免出现OOM;
- 在Application中初始化数据时,加入进程判断,确保在自己需要的进程进行初始化,特别是在后台进程中尽量避免不必要的初始化;
- 如非必要,尽量少创建线程,建议用线程池对线程进行管理;
- 创建线程池使用ThreadPoolExecutor创建,而不是Executor,这样可以使开发者更加明白线程池的运行规则,避免资源消耗;
- 新建线程时,定义自己能识别的业务线程名称,便于性能优化和功能排查;
- ThreadPoolExecutor创建时设置存活时间(setKeppAliveTime),确保空闲时,线程及时被释放;
- 不要用SharedPreferences用于进程数据共享;
- 进程间数据共享中,使用数据库,而不是sp,文件,以及Intent直接传递;
文件和数据库
- 任何时候不要使用硬编码文件路径,使用Android文件系统API进行访问;(Environment)
- 使用外部存储时,必须先检查外部存储的可用性;
- 应用间共享文件时,不能使用放宽文件系统访问权限的方式,而使用FileProvider;
- SharedPreferences提交数据时,尽量使用Editor#apply()方法,而不是Editor#commit()方法。一般来讲,只有当确定提交结果,并根据结果有后续操作时,才能用Editor#commit()方法;
- 数据库Cursor使用完毕后,一定要记得关闭,以免造成内存泄漏;
- 多线程操作使用数据库时,需要使用事务,以免出现同步的问题;db.beginTransaction;db.setTransactionSuccessful,使用完毕db.endTransaction;
- 数据库进行大数据操作时,尽量使用事务或者其他方式,来保证执行的效率;
- 执行数据库语句时,使用SQLiteDataBase#insert()、delete()、update()等方法,不要使用SQLiteDatabase#exeSQL(),以免SQlite注入风险;
- 如果ContentProvider中存储的数据在SQL中,应该避免直接将外来不受信任的数据直接拼接在原始数据库语句中,使用一个将“?”作为可替换参数的选择句子,或者使用一个单独的选择参数数组,能有效避免SQL注入风险。
例:String mSelectionCause=”var=?”;
String selectionArgs[] ={“”};
Bitmap、动画、drawable
- 加载大图片或者多图片时,应该使用异步操作,因为图片的加载涉及IO操作,以及CPU密集操作,很可能引起卡顿;
- 在ListView、ViewPager、RecyclerView、GridView中使用图片时,及时做好图片的缓存,避免始终持有图片,导致内存泄漏。也避免重复创建图片, 导致性能降低。建议使用Fresco、Glide框架来加载图片;
- Png图片使用tinyPng或者类似的工具进行压缩处理,减少包体积;
- 图片使用完毕之后,及时回收资源,释放内存;
- 使用ARGB-565替换ARGB-888,在视觉要求不高的情况下,能有效减少内存占用;
- 在Activity中的onPause方法和onStop方法中,停止当前页面动画的播放;
安全和信息安全规范
- 使用PendingIntent时,禁止使用空的Intent以及隐式意图;
- 禁止使用常量初始化矢量参数构建IvParameterSpec,建议IV通过随机方式产生;
- 将android:allowbackup属性设置为false,防止adb backup导出数据;
- 在实现的HostnameVerifier子类中,需要使用verify函数校验服务器主机名的合法性,否则会导致恶意程序利用中间人攻击绕过主机名校验;
- 利用X509TrustManager子类中的checkServerTrsuted函数校验服务端证书的合法性;
- META-INF目录中不能包含apk,odex,so等敏感文件,该文件没有经过签名,容易被恶意替换;
- Receiver/Provider不能再汉武权限控制的情况下,将android:export设置为true;
- 阻止WebView通过filsescheme方式访问本地敏感数据;
- 不要广播敏感信息,只能在本应用中使用LocalBroadcast,避免被别的应用手动,或者setPackage做限制;
- 不要把敏感信息打印到Log日志中;
- 对于内部使用的组件,显示设置组件的android:exported属性为false;
- 应用发布前确保android:debuggable属性设置为false;
- 使用IntentScheme URL需要做过滤;
- 除非min API level>=17,请注意addJvascriptInterface的使用;
- 传输使用Https协议证书至少强校验;
- 敏感数据要进行加密传输;
- 前端数据不可信,后端数据要校验;
- 敏感系统使用VPN进行连接;
- 本地不能明文保存个人敏感数据,敏感数据要加密保存;
- 本地不能保存账号和密码;
- 不要使用MSG传递大的对象,会导致内存问题;
- 不要使用system.out.print打印log日志;
- Log日志中的tag不能为空;