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