2018-09-18 - Android代码规范

开发手册 - 小知识补充

目录:
1、Android组件
2、UI与布局
3、进程、线程与消息通信
4、文件与数据库
5、Bitmap、Drawable 与动画
6、安全
7、其他

一、Android组件

1.1、Activity之间需要传递大数据量的时候避免使用Intent+Parcelable的方式。

EventBus替代,以避免造成TransactionTooLargeException
Lisa's EventBus Demo

1.2、耗时操作
  • 避免在Service#onStartCommand()/onBind()方法中执行耗时操作。
    • 如果有耗时操作,用IntentService来替代Service或者采用其他的异步机制
  • 避免在BroadcastReceiver#onReceive()中执行耗时操作
    • 有耗时工作,创建IntentService完成。
      BroadcastReceiver#onReceive()方法耗时超过10秒可能被系统杀死
  • 不要在onPause()中执行耗时操作。
    • 如果在onPause方法中做耗时操作,可能会影响页面跳转,造成卡顿
1.3、避免使用隐式Intent广播敏感信息。避免被其他APP接收

仅限于应用内的广播,用LocalBroadcastManager#sendBroadcast()

LocalBroadcastManager.getInstance(context)
                     .registerReceiver(receiver, filter);
LocalBroadcastManager.getInstance(context)
                     .unregisterReceiver(receiver);
1.4、不要在Activity.onDestroy()执行资源释放工作

因为onDestroy()执行的时间可能比较晚。
Activity#onPause()/onStop()中用Activity.isFinishing()方法来判断是否APP处于预备销毁的阶段,然后做对应的资源销毁工作。

而且,假设Activity的引用还被其他部分所持有,那么很可能会一直不执行onDestroy()方法,在这种情况下如果资源释放工作都放在onDestroy()里面,很可能导致内存溢出。

    @Override
    protected void onPause() {
        super.onPause();
        if(isFinishing()){
            // 资源可以释放了。。。
        }
    }
  • Activity.isFinishing()
    • true : Activity处于待回收状态
    • false:Activity处于活跃状态
  • Activity.isDestroyed()
    • true:Activity已经执行过onDestroy()方法
    • false:Activity还没执行onDestroy()方法
1.5、如果要创建Service,尽量用IntentService
1.6、全局定义一个Toast对象,避免出现连续显示吐司时无法取消上一次吐司。
  • 原来的ToastUtils:
public class ToastUtils {

    private ToastUtils() {
            /* cannot be instantiated */
        throw new UnsupportedOperationException("cannot be instantiated");
    }

    public static boolean isShow = true;

    public static void showShort(Context context, CharSequence message) {
        if (isShow){
            Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
        }
    }
}
  • 改良后的ToastUtils:
**
 * Toast要全局定义统一的一个对象,避免出现Toast无法销毁的情况
 * @author Lisa
 * @date 2018/9/18
 */

public class ToastUtils {

    private Toast mToast;
    private static ToastUtils mToastUtils;

    private ToastUtils(Context context) {
        mToast = Toast.makeText(context.getApplicationContext(), null, Toast.LENGTH_SHORT);
    }

    public static synchronized ToastUtils getInstanc(Context context) {
        if (null == mToastUtils) {
            mToastUtils = new ToastUtils(context);
        }
        return mToastUtils;
    }
    /**
     * 显示toast
     *
     * @param toastMsg
     */
    public void showToast(String toastMsg) {
        mToast.setDuration(Toast.LENGTH_LONG);
        mToast.setText(toastMsg);
        mToast.show();
    }

    /**
     * 显示toast
     *
     * @param toastMsg
     */
    public void showShortToast(String toastMsg) {
        mToast.setDuration(Toast.LENGTH_SHORT);
        mToast.setText(toastMsg);
        mToast.show();
    }

    /**
     * 显示toast
     *
     * @param toastMsg
     */
    public void showLongToast(String toastMsg) {
        mToast.setDuration(Toast.LENGTH_LONG);
        mToast.setText(toastMsg);
        mToast.show();
    }

    /**
     * 取消toast,在activity的destory方法中调用
     */
    public void destory() {
        if (null != mToast) {
            mToast.cancel();
            mToast = null;
        }
        mToastUtils = null;
    }

}

最后在Activity#onDestroy()调用销毁Toast

 ToastUtils.getInstanc(getActivity()).destory();
1.7、使用 Adapter 注意事项

如果使用了 ViewHolder 做缓存,在 getView()的方法中无论这项convertView的每个子控件是否需要设置属性(比如某个 TextView 设置的文本可能为 null,某个按钮的背景色为透明,某控件的颜色为透明等),都需 要为其显式设置属性(Textview的文本为空也需要设置 setText(""),背景透明也需要 设置),否则在滑动的过程中,因为 adapter item 复用的原因,会出现内容的显示错乱。

二、UI与布局

2.1、布局
  • ViewGroup不得不多重嵌套时,RelativeLayout可有效降低嵌套数

    • measure、layout、draw耗费的总时间尽量控制在16ms以内。
    • Hierarchy Viewer 工具查看多余的ViewStetho似乎也可以看。
      • AndroidStudio3.1开始Layout Inspector替代了Hierarchy Viewer。不管怎么说我用Stetho看好了
  • 文本大小用sp,View大小用dp,文字大小不要小于12sp

  • 不要多次在子View和父View中一起设置背景造成过度绘制。不需要用的布局及时隐藏掉。

  • 学习用Merge\ViewStub来优化布局,尽可能减少UI层级

    • 优先用FrameLayout,然后再考虑LineayLayout\RelativeLayout.
  • 在需要时刻刷新某一区域的组件时,避免layout全局刷新

    • 具体看开发手册
2.2、用DialogFragment替代Dialog/AlertDialog

使对话框或浮层的生命周期能够随着Activity的生命周期走。

2.3、源文件统一用UTF-8进行编码
2.4、尽量不要使用 AnimationDrawable

三、进程、线程与消息通信

3.1、线程与线程池
  • 线程要由线程池提供
  • 线程池用ThreadPoolExecutor创建
  • 要给每条线程命名,方便回溯
  • 要设置线程存活时间setKeepAliveTime,尽早释放资源

四、文件与数据库

4.1、不要硬编码文件路径

/sdcard/storage....在项目中都不要这样直接写这样的路径。

 android.os.Environment#getExternalStorageDirectory() 
 android.os.Environment#getExternalStoragePublicDirectory()
 android.content.Context#getFilesDir()
 android.content.Context#getCacheDir
4.2、SharedPreserences只存放简单的数据类型

其他的考虑用文件或数据库

4.3、大数据写入数据库时,请使用事务或其他能够提高 I/O 效率的机制,保证执行速度。
4.4、多线程操作写入数据库时,需要使用事务,避免出现同步问题

五、BitmapDrawable 与动画

5.1、图片加载
  • 异步加载
  • 列表展示时做好图片缓存
  • png图片要用压缩工具压缩以减小包体积,tinyPng 、webp
    • 在AndroidStudio中选中要压缩的图片,右击选择convertToWebp
5.2、Bitmap使用
  • 用完及时recycle释放资源
  • 使用 ARGB_565 代替 ARGB_888可解决一定的OOM问题
5.3、如果为了节省包体积,可以在不影响UI效果的前提下,省略低密度图片。
5.4、动画
  • 页面退出时要关闭停止动画
    • onPause()\ onStop()中停止动画
  • 动画或其他异步任务结束时,在回调中要注意判断资源是否已被释放掉了,避免空指针
  • 动画执行结束要释放相关资源:View.clearAnimation()

anim.setAnimationListener(new AnimationListener() {
    @Override
    public void onAnimationEnd(Animation arg0) {
    //判断一下资源是否被释放了 
        if (v != null) {
         v.clearAnimation(); 
        }
    }
});

六、安全

6.1、IntentPendingIntent
  • 用于构造PendingIntentIntent要指定ComponentName或者Action
  • 用于构造PendingIntentIntent不可以是隐式的Intent
6.2、AndroidManifest
  • android:allowbackup 属性设置为 false,防止 adb backup 导出数据。
  • Receiver/Provider在毫无权限控制的情况下,不要将 android:export 设置为 true。
  • 内部使用的组件,将android:export 设置为 false。
6.3、应用上线注意事项:
  • 不要把敏感信息打印到日志中,线上版本要关闭调试接口
  • 确保把android:debuggable属性设置为false
6.4、加密
  • 秘钥不要硬编码到程序中
  • 使用 AES/DES/DESede 加密算法时,不要使用默认的加密模式 ECB,应显示指定使用 CBC 或 CFB 加密模式。
  • 不要用不安全的Hash算法(MD5、SHA-1)做加密,用SHA-256安全系数更高

七、其他

7.1、不要用System.out.println("")打印
7.2、Log要定义好Tag
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容

  • 面试必背 会舍弃、总结概括——根据我这些年面试和看面试题搜集过来的知识点汇总而来 建议根据我的写的面试应对思路中的...
    luoyangzk阅读 6,739评论 6 173
  • 面试题总结 通用 安卓学习途径, 寻找资料学习的博客网站 AndroidStudio使用, 插件使用 安卓和苹果的...
    JingBeibei阅读 1,645评论 2 21
  • 本文出自 Eddy Wiki ,转载请注明出处:http://eddy.wiki/interview-androi...
    eddy_wiki阅读 3,252评论 0 20
  • 在每個男人的生活上,到了某個時間點,他會體悟到,有時候還帶著相當複雜的沮喪,自己的單純需求與這個老於世故的現實社會...
    2ca0fa5d0ca8阅读 631评论 2 3
  • 越来越喜爱文字的东西 因为它能说出心声 像个伴 给孤独的流浪人 一种慰藉 一个拥抱 一曲长歌 引导我们这些人 走向...
    暂无所依阅读 439评论 5 9