博客
关于我
android全方位性能优化方法
阅读量:619 次
发布时间:2019-03-13

本文共 2948 字,大约阅读时间需要 9 分钟。

布局优化

布局优化的核心思想是通过减少布局文件的嵌套层级,降低Android绘制过程的复杂度,从而提升程序性能。优化之道主要包括:

  • 精简无用控件和层级:删除布局中不再使用的控件或嵌套层级,避免在绘制时产生不必要的计算开销。
  • 合理选择ViewGroup类型:尽量采用性能较低的ViewGroup,如RelativeLayout,减少高消耗的布局计算。
  • 标签和ViewStub也是优化布局的一种高手。标签通过布局重用降低了内存占用和绘制复杂度,而ViewStub则实现了按需加载控件功能,进一步提升了性能表现。


    绘制优化

    绘制优化主要关注在View的onDraw方法中是否存在耗时操作。避免频繁创建局部对象或执行复杂循环操作:

  • 避免局部对象创建:onDraw方法中大量创建临时对象会占用内存并引发频繁的垃圾回收,影响程序流畅度。
  • 避免耗时操作:onDraw是绘制循环中的关键环节,千万不能在此处执行复杂的非绘制任务,如循环操作或网络请求,以免拖慢整个绘制过程。

  • 内存优化

    内存泄露是移动开发中的常见隐患,主要表现为静态变量或长生命周期对象未被释放。常见场景包括:

  • 静态变量引发的内存泄露

    例如,静态变量引用了Activity自身或其他长生命周期对象,导致无法正常释放。

    public class MainActivity extends Activity {          private static View sView;           @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);                  sView = new View(this);              }           // Activity无法销毁,sView持有 dù Activity已经不可见}
  • 单例模式引发的内存泄露

    单例模式通过静态单例Holder实现长生命周期,但如果没有及时解注册,会导致关联的非静态对象无法释放。

    public class TestManager {          private static class SingletonHolder {                  public static final TestManager INSTANCE = new TestManager();          }          private TestManager() {}          public static TestManager getInstance() {                  return SingletonHolder.INSTANCE;          }      }

    如果某 Activity注册了这个单例而未取消注册,会导致内存泄露。

  • 属性动画引发的内存泄露

    如果不停止 ObjectAnimator 的循环动画,会导致 Activity 的 View 被动画持有,进而引发内存泄露。

    protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    ObjectAnimator animator = ObjectAnimator        .ofFloat(mButton, "rotation", 0, 360)        .setDuration(2000)        .setRepeatCount(ValueAnimator.INFINITE)        .start();    // 注意:未调用 cancel() 会导致内存泄露}

  • 响应速度优化

    响应速度优化的核心是减少主线程上的阻塞操作,避免触发ANR(application not responsive)。具体措施包括:

  • 移交耗时任务:将耗时操作(如网络请求、数据库查询)放至子线程执行。
  • 性能调优Activity启动:尽量减少 onCreate 方法中的初初始操作,如避免复杂的UI更新或耗时数据处理。
  • 利用ANR日志分析:当发生ANR时,系统会写入 /data/anr/ 文件,可以通过分析 traces.txt 确定具体原因。例如以下代码会导致长时间ANR:
    protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    SystemClock.sleep(30 * 1000); // 30秒会引发ANR}

  • ListView 和 Bitmap 优化

  • Listview 优化

    • ViewHolder模式:避免在每次getView中重复创建新控件,直接用ViewHolder持有引用。
    • 减少列表更新:根据滑动状态控制数据加载或更新,避免在滚动过程中执行大量操作。
    • 硬件加速:开启硬件加速可以提升ListView的滑动流畅度。
  • Bitmap优化

    使用BitmapFactory.Options进行图片采样,避免将大图尺寸加载到内存中。例如:

    BitmapFactory.Options options = new BitmapFactory.Options();options.inSampleSize = 2; // 设定采样比例Bitmap bitmap = BitmapFactory.decodeResource(resId, options);

  • 线程优化

    线程优化的目标是合理使用线程池,避免主线程被阻塞。推荐使用线程池进行耗时操作:

    • 使用 ExecutorService 和线程池执行任务,例如:
      public class MyTask {    public static void executeTask(String task) {        Executors.newSingleThreadExecutor().execute(task);    }}
    • 线程资配:通过线程池控制最大并发数,防止线程爆炸和资源耗尽。

    其他性能建议

  • 减少对象创建:避免频繁创建对象,尽可能复用现有资源。
  • 优化枚举类型:枚举类型占用内存较大,可以考虑使用整型或 SparseArray。
  • 使用static final 常量:避免内存泄露风险,减少堆ائلة中的消耗。
  • 合理使用软引用和弱引用:适用于不需要长期持有对象的场景。
  • 优化数据结构:使用SparseIntArray等高效数据结构,减少内存占用。
  • 规范命名风格
    • 私有变量以 mm_开头。
    • 静态变量以 s_ 开头。
    • 常量全大写。
  • 层次化代码结构:将单一逻辑分解为多个小函数,便于维护和阅读,避免单一职责过于模糊。
  • 转载地址:http://vzboz.baihongyu.com/

    你可能感兴趣的文章
    推荐几篇近期必看的视觉综述,含GAN、Transformer、人脸超分辨、遥感等
    查看>>
    ERROR 1840 (HY000) at line 24: @@GLOBAL.GTID_PURGED
    查看>>
    BUU-MISC-caesar
    查看>>
    【专题3:电子工程师 之 上位机】 之 【46.QT音频接口】
    查看>>
    一文理解设计模式--命令模式(Command)
    查看>>
    VTK:可视化之RandomProbe
    查看>>
    block多队列分析 - 2. block多队列的初始化
    查看>>
    Java时间
    查看>>
    不编译只打包system或者vendor image命令
    查看>>
    The wxWindows Library Licence (WXwindows)
    查看>>
    【编程】C语言入门:1到 100 的所有整数中出现多少个数字9
    查看>>
    flink启动(二)
    查看>>
    pair的用法
    查看>>
    Flex 布局的自适应子项内容过长导致其被撑大问题
    查看>>
    PL/SQL 动态Sql拼接where条件
    查看>>
    Lua-table 一种更少访问的安全取值方式
    查看>>
    虚函数
    查看>>
    Error:Cannot read packageName from AndroidManifest.xml
    查看>>
    【自学Flutter】4.1 Material Design字体图标的使用(icon)
    查看>>
    【换行符】什么时候用cin.get()吃掉输入流中的换行符
    查看>>