Android 代码优化篇

一、数据结构的选择

1、Array、ArrayList、List、LinkedList、HashMap、HashSet、HashTable区别

Array

数组(Array):是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据, 并且不支持动态扩容。

线性表
线性表就是数据排成一条线一样的数据结构,每个线性表最多只有前后两个方向,数组,链表丶队列丶栈等都是线性表数据结构。

非线性表
非线性表就是数据不规则,与线性表是相对立的,比如二叉树丶堆丶等,在非线性表中,数据之间并不是简单的前后关系。

优点:在内存中是连续存储,索引速度非常快,赋值与修改元素简单.

缺点:在声明的时候必须说明它所存储的元素类型、长度,数组的长度过长,会造成内存浪费,数组和长度过短, 会造成数据溢出的错误。数组在插入、删除元素效率差。

ArrayList

优点:

  • 在声明ArrayList的时候并不需要声明它的类型、长度,因为容量可动态增长。
  • ArrayList存入对象时,抛弃类型信息,所有对象屏蔽为Object,编译时不检查类型,但是运行时会报错。

缺点:

  • 数组扩容是对ArrayList效率影响比较大的一个因素。
  • 每当执行Add、AddRange、Insert、InsertRange等添加元素的方法,都会检查内部数组的容量是否不够了,如果是,它就会以当前容量的两倍来重新构建一个数组,将旧元素Copy到新数组中,然后丢弃旧数组,在这个临界点的扩容操作,应该来说是比较影响效率的。
  • 不是类型安全。
  • 装箱与拆箱的过程是很损耗性能的。

List集合

  • 是类型安全,需要说明存储的数据类型。
  • List不能被构造,但可以向上面那样为List创建一个引用,而ListArray就可以被构造。
  • List泛型的好处:
      通过允许指定泛型类或方法操作的特定类型,泛型功能将类型安全的任务从您转移给了编译器。不需要编写代码来检测数据类型是否正确,因为会在编译时强制使用正确的数据类型。减少了类型强制转换的需要和运行时错误的可能性。泛型提供了类型安全但没有增加多个实现的开销。

LinkedList

  • LinkedList也是List接口的实现类。
  • LinkedList是一个双向链表。链表数据结构的特点是每个元素分配的空间不必连续、插入和删除元素时速度非常快、但访问元素的速度较慢。
  • 添加和删除元素时具有比ArrayList更好的性能。但在元素的查询和修改方面要弱于ArrayList。

HashTable与HashMap、HashSet

  • 同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的。
  • HashMap允许存在一个为null的key,多个为null的value 。
  • hashtable的key和value都不允许为null。
  • HashSet实现Set接口,底层是由哈希表实现(实际上是HashMap),Set里面的元素无序不重复,可以允许null值。

二、Handler正确使用

private static class  InnerHandler extends Handler{
        private final WeakReference<MainActivity> mActivity;

        private InnerHandler(MainActivity activity) {
            mActivity = new WeakReference<MainActivity>(activity);
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            MainActivity activity = mActivity.get();
            if(activity!=null){
                
            }
        }
    }

三、正确使用Context 

单例的正确使用 

public class SingleInstance {
    private Context mContext;
    private static SingleInstance sInstance;

    private SingleInstance(Context context) {
        mContext = context;
    }

    public static SingleInstance getInstance(Context context) {
        if (sInstance == null) {
            sInstance = new SingleInstance(context.getApplicationContext());
        }
        return sInstance;
    }
}

 不同Context的对比

四、掌握Java的四种引用方式

强引用:java里面使用最广泛的一种,也是对象默认的引用类型。如果一个对象具有强引用,那么垃圾回收期是不会对它进行操作的,当内存空间不足时,Java虚拟机将会抛出OutOfMemoryError错误,这时应用将会终止运行。

软引用:一个对象如果只有软引用,那么当内存空间充足时,垃圾回收期不会对它进行回收的操作,只有内存不足时,这个对象才会被回收。

弱引用:当垃圾回收器扫描到只具有弱引用的对象时,不论当前的内存空间是否不足,都会对弱引用对象进行回收。

虚引用:虚引用不会对所指向的对象生命周期产生任何的影响,会按照它原来的方式被垃圾回收器回收,虚引用本质上只是一个标记作用,主要用来跟踪对象被垃圾回收的活动,虚引用必须和引用队列配合使用,当对象被垃圾回收时,如果存在虚引用,那么Java虚拟机会将整个虚引用加入到与之关联的引用队列中。

五、编码习惯

  1. XML减少不必要的成员变量;
  2. 尽量不要使用枚举,少用迭代器;
  3. 对Cursor、Receiver、Sensor、File等对象,要注意它们的创建、回收与注册、反注册;避免大量使用注解、反射;
  4. 广播事件记得注销,webview对象退出界面,记得销毁、置空。
  5. 对象无需引用,则置空为null,方便检测被垃圾内存。
  6. 多用基本数据类型,少用它们的引用数据类型。例如Integer会比int所占大。
  7. 少用static修饰变量,被修饰的全局性的变量是不会被GC回收的。
  8. 字符串拼接要用StringBuffer(用append拼接)替代String,String每多一个“+”,就会多创建一个对象。
  9. bitmap、游标Cursor、IO或者文件流等不用时候,记得回收。尤其是图片的加载而占用内存较大,可以做图片质量或者物理大小的压缩。
  10. 避免在频繁绘制的ondraw方法中创建对象。
  11. 防止单例类长久持有不用对象的引用,可尝试传入ApplicationContext。
  12. 非静态内部类导致内存泄露,比如Activity中创建的Handler,可以尝试弱引用去拿到外部的对象引用。
  13. 广播的注销,页面Activity退出时未执行完的Thread的注销或者Timer还在执行定时任务的注销等等。
  14. Activity结束时候,需cancel掉属性动画。
  15. webview退出的销毁。

《Android高级进阶》

https://www.jianshu.com/p/cd7552bdaf6e

https://blog.csdn.net/zhuolou1208/article/details/78095293

https://blog.csdn.net/qq_30257149/article/details/99588189

发布了49 篇原创文章 · 获赞 2 · 访问量 8584

猜你喜欢

转载自blog.csdn.net/yangjunjin/article/details/105158956