Android项目中的优化 -- 布局优化

0. 概念

  • 从上次讲到的启动过程,ActivityThread建立了Activity以后,会将 DecorView添加到Window上去,同时创建ViewRootImpl对象,并且把这个对象和DecorView建立关联,绘制流程就是从ViewRoot的performTraversals开始的,然后measure、layout、draw过程。
  • DecorView就是我们看到的Activity的顶层View,他包含的LinearLayout把画面分成上下两部分,上面就是标题栏,下面是contentView,就是Activity->onCreate->setContentView的部分,然后setContentView里面就是onMeasure、onLayout、onDraw过程。
  • 优化主要是上面setContentView中的三个过程,并且自定义View和ViewGroup中的这三个过程。

1. 工具

既然是优化,肯定要能看到效果,所以要有数据显示证明优化确实起到了作用

有了上面两个工具就可以直观的看到优化的效果了

2. 优化方法

  1. LinearLayout效率优于RelativeLayout(同样布局嵌套的情况下),
    RelativeLayout会onMeasure两次
  2. 不带weight的LinearLayout效率优于带weight的LinearLayout,
    weight属性会onMeasure两次
  3. RelativeLayout有利于减少布局的嵌套,LinearLayout只能必须指定子View的方向
  4. ConstraintLayout 优于任何布局(只是学习了解真正项目中还没用过),学习文章ConstraintLayout
  5. include 和 merge :布局复用,比如toolbar布局
  6. ViewStub :懒加载布局,初始化的时候不会初始化ViewStub,比如每个网络请求页面都有的加载失败、网络错误、未登录等页面
  7. Space:一般用于分割线,onDraw函数是空了,效率高,比如个人中心中的分割线
  8. 不要在Activity的主题中为Activity设置默认的背景图片,这样会导致Activity占用的内存翻倍
  9. 用SurfaceView和TextureView 绘制复杂布局和高清大图(也可以使用BitmapRegionDecoder来加载),因为他们都是在非UI线程绘制UI,不会阻塞主线程(项目中还未用到,需要研究).
  10. Button的点击效果:
    尽量不要用两个图片来设置selector,会占用两倍内存
    尽量用纯颜色设置点击效果
    必须有图片的(业务要求),尽量用.9.png图片
    不能用.9.png的用懒加载方式
view.setOnTouchListener(new OnTouchListener() {
               @Override
               public boolean onTouch(View v, MotionEvent event) {
                   switch(event.getAction()){
                   case MotionEvent.ACTION_DOWN:{
                       v.setBackgroundResource(pressResId);
                   }
                   break;
                   case MotionEvent.ACTION_MOVE:{
                       v.setBackgroundResource(pressResId);
                   }
                   break;
                   case MotionEvent.ACTION_UP:{
                       v.setBackgroundResource(normalResId);
                   }
                   break;
                   default:{
                       
                   }
                   break;
                   }
                   return false;
               }
           });
  1. ImageView的点击效果也用onTouch事件,用setColorFilter来实现效果,不要用两张图片
  2. Material Design效果的控件原生都支持点击效果,都不用两张图片
  3. 尽量合并子控件减少布局嵌套,比如ImageView和TextView可以转换成TextView+drawable等情况
  4. recyclerview scrollview 尽量不嵌套,可以给recyclerview添加addHeader方法来减少嵌套

3. RecyclerView优化

这个是布局优化的主要部分,因为一个APP中有太多的RecyclerView(以前是ListView),而且卡顿现象一般都在RecyclerView的快速滑动中。

  • 首先ViewHolder模式现在是必须用的
  • 还是前面说的布局尽量不要嵌套
  • 在Item里面尽量不要做耗时的操作,网络请求、IO操作、复杂计算等,异步任务也尽量不要多开
  • 快速滑动的时候,可以考虑停止加载耗时任务,降低异步任务的执行频率
  • 要用tag绑定来防止item错乱
  • 开启硬件加速 有时候能解决卡顿现象
  • 背景色什么的尽量不要半透明,会执行大量计算操作

4. Android适配方案

  • DP方案,这是Google开始推荐的方案
    优点:在相似分辨率下,看起来效果一样,就是绝对大小一样
    缺点:在相差很大的分辨率和大小下,效果差别太大,Google建议在且一套图出来
    实际项目中使用过,但是效果太差,而且再切一套图不太现实
  • 资源目录名方案,这是官方文档在上面基础上推荐的方案
    优点:通过运行时找到不同的命名文件来达到适配效果,比上一种方案好很多,只要适配了这个机型就会达到预想的效果
    缺点:市场上机型太多,很难适配完全,并且修改起来也很麻烦(虽然有自动生成工具),太耗时
    实际项目中使用过,整体效果还好,但是确实有客户反映UI变形了等问题还有修改起来太麻烦
  • ConstraintLayout方案:Google推荐
    优点:约束布局直接就能适配不同机型
    缺点:没有用过,也没研究很深,据说有坑
  • AutoLayout方案:网上大牛们基于Google百分比方法开源的方案
    优点:操作简单,适配效果不错
    缺点:代码中动态修改UI大小会出现问题,并且作者不维护了
    目前用的这个方案,出现的问题自己代码里面特殊处理
  • Rudeness: 网上基于AutoLayout改进的方案
    没有使用过,正在调研,据说解决了AutoLayout的问题,不知道有没有新问题出现

5. 自定义View

onCreate -> onFinishInflate -> onAttachToWindow -> onMeasure -> onSizeChanged -> onLayout -> onDraw -> onDetachedFromWindow
注意点:
0. onFinishInflate是xml加载完成以后调用
1. onDetachedFromWindow 在这里做释放对象、资源和结束线程的操作
2. invalidate() 和 postInvalidate() 是主动调用onDraw的方法
3. requestLayout() 是主动调用onMeasure 和 onLayout的方法
4. 如果有动画只是调用onDraw没有调用onMeasure 和 onLayout,所以View的实际大小没有改变
5. 测量模式下的三种模式MeasureSpec.UNSPECIFIED、MeasureSpec.EXACTLY、MeasureSpec.AT_MOST
6. 重写onMeasure方法的时候,要特别处理MeasureSpec.AT_MOST和View的padding这两种情况,在测量出宽高以后,一定要设置setMeasuredDimension这个函数.
7. 自定义View主要处理onMeasure,自定义ViewGroup主要处理onLayout,如果是组合View或者ViewGroup主要处理onDraw
8. canvas操作

        canvas.translate(100, 50) 平移
        canvas.scale(2, 4); 缩放
        canvas.rotate(30); 旋转
        canvas.save(); 保存状态
        canvas.restore(); 恢复状态
        canvas.drawText(); 画文字
        canvas.drawCircle(); 画圆
        canvas.drawLine(); 画线
        canvas.drawOval(); 画椭圆
        canvas.drawArc(); 画弧度
        canvas.drawRoundRect(); 画矩形
        canvas.drawPath(); 画多边形
        canvas.drawPath(); 画贝塞尔曲线
        canvas.drawBitmap(); 画图片
        简单有规则的东西直接画,复杂的用Path
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容