Android 性能典范:拯救计划

gysjxn 9年前
   <h2><strong>前言</strong></h2>    <p>今天逛稀土时偶然看到 <a href="/misc/goto?guid=4959670090860815789" rel="nofollow,noindex">hanks</a> 分享的一篇英文文章,粗略浏览便已觉得不错,因此翻译成中文,与君分享。</p>    <p>原文地址: <a href="/misc/goto?guid=4959670090954001063" rel="nofollow,noindex">Android Performance Patterns: Rescue tips</a></p>    <h2><strong>正文</strong></h2>    <p>现在的app到处都充斥着华丽的动画、复杂的转化还有自定义View,然而用户体验必须尽可能直观且类似。以下这些范例将会帮助你做出一个流畅的、快速响应的、甚至可能减少电量损耗的app,这些范例由一些可以提升整体应用表现的微优化组成。</p>    <h3><strong>避免“坏”表现</strong></h3>    <ul>     <li>避免堵塞主线程</li>     <li>避免可能引发大范围重绘的不必要的重绘</li>     <li>用 RelativeLayout 来减少布局层级</li>     <li>避免在 LinearLayout 中使用嵌套的 weight 属性(因为weight属性会使每个子View进行两次measure)</li>     <li>避免使用没有恰当处理的自定义View</li>     <li>避免创建没必要的对象</li>     <li>将常量声明为 static final(static比普通变量快 15% - 20%)</li>     <li>使用基本数据类型(Integer、Float 比基本类型慢两倍)</li>     <li>避免内部的 getter 和 setter(直接访问属性可以快3倍)</li>     <li>使用改进的循环语法【译者注:这里应该是指for each循环】</li>     <li>对私有的内部类考虑使用包访问级别代替私有访问级别</li>     <li>谨慎使用native方法</li>    </ul>    <h3><strong>自定义View</strong></h3>    <ul>     <li>遵循KISS原则</li>     <li>在布局中使用merge标签来作为根标签(避免额外的ViewGroup)</li>     <li>使用include标签(便于布局的复用)</li>     <li>避免不必要的布局</li>     <li>不要在onDraw中申请内存或者做复杂逻辑</li>     <li>去除不必要的invalidate()调用</li>     <li>考虑创建自己的ViewGroup</li>     <li>用RecyclerView替代ListView和GridView</li>    </ul>    <h3><strong>避免内存抖动</strong></h3>    <p>1, 不可变对象:String</p>    <ul>     <li>不要申请大量不必要的对象内存:</li>     <li>2, 自动装箱:Integer, Boolean...</li>     <li>考虑使用对象池并缓存来减少内存抖动</li>     <li>留心enum类型的开销(一个指向枚举类型的引用就要占据4个字节)</li>    </ul>    <h3><strong>避免内存泄漏</strong></h3>    <ul>     <li>不要在内部类里泄漏context实例</li>     <li>不要在activity里泄漏view实例</li>     <li>使用内部静态类优于非静态的</li>     <li>除非键都是WeakReference,否则不要使用WeakHashmap作为缓存</li>    </ul>    <h3><strong>CPU</strong></h3>    <ul>     <li>不要嵌套多通路布局</li>     <li>当需要时才去进行复杂的计算【译者注:类似懒加载】</li>     <li>缓存复杂计算的结果以复用</li>     <li>考虑 RenderScript 的性能</li>     <li>尽可能减少主线程的工作</li>    </ul>    <h3><strong>避免过度绘制</strong></h3>    <ul>     <li>精简drawable</li>     <li>在透明部分使用.9图</li>     <li>设置view的透明度时多注意</li>     <li>去除view中无用的背景</li>    </ul>    <h3><strong>bitmap</strong></h3>    <ul>     <li>将bitmap解码为需要的尺寸:BitmapFactory.Options(</li>     <li>inSampleSize, inDensity, inTargetDensity)</li>     <li>加载bitmap到内存时,设置尺寸为显示尺寸</li>     <li>如无必要不要进行缩放</li>     <li>使用LRU缓存</li>    </ul>    <h3><strong>Service</strong></h3>    <ul>     <li>除非Service在处理事务否则不要让其保持运行。同时也要小心stopService当Service工作完成时</li>     <li>系统倾向保留有Service运行的进程,那么被service占用的内存将无法被其他进程使用或者被内存置换</li>     <li>限制service生命周期的最佳实践是使用IntentService,它会在工作完成后结束自身</li>     <li>让没必要存活的Service继续运行是Android app内存管理最差的举动之一</li>    </ul>    <h3><strong>线程</strong></h3>    <p>在线程的run()方法中使用 </p>    <ul>     <li>Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND)可以减少该线程及UI线程的计算性能损耗</li>     <li>如果你没有通过这种方式为线程设置低优先级,那么该线程仍会拖慢你的app,因为默认情况下它的优先级与UI线程的优先级相同</li>     <li>维护住当前线程的引用,以便你之后可能先打断该线程。例如:当网络连接失败你可以取消该线程</li>    </ul>    <p>避免ANR</p>    <ul>     <li>UI线程中做的事越少越好</li>     <li>如果应用正在后台响应用户的输入,最好显示进度给用户(例如显示一个进度条)</li>     <li>使用Systrace或Traceview等性能工具来检测应用响应能力的瓶颈</li>     <li>如果你的应用有一个非常耗时的初始化过程,考虑使用启动页或者尽快渲染主要的view,表明正在加载中并且正在显示异步的信息</li>    </ul>    <p>原文链接: <a href="/misc/goto?guid=4959670091036631155" rel="nofollow,noindex">http://www.jianshu.com/p/efcb36b7ce48</a></p>