Android面试题总结(二)

来源:互联网 发布:sql语句修改字段属性 编辑:程序博客网 时间:2024/05/21 00:52

八、请写出两种单例模式

单例模式是一种常见的设计模式,在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。正是由于这个特点,单例对象通常作为程序中的存放配置信息的载体,因为它能保证其他对象读到一致的信息。这种方式只需访问该单例对象即可达到统一,但是在多线程环境下,随着应用场景的不同,也可能带来一些同步问题
应用场景:窗口管理系统、打印缓冲池、文件系统它们都是单例原型的例子。
饿汉模式:

/** * 演示单例模式之饿汉模式 * @author Administrator * */public class EagerSingleton { // 在定义的时候就初始化instance,    private static EagerSingleton  instance=new EagerSingleton();     // 构造函数必须是私有的,不能被外部直接调用。     private EagerSingleton()    {          }     // 暴露给外部,提供实例。    public   static  EagerSingleton  getSingleInstance()    {              return instance;    }}

在加载类的时候就实例化了对象,如果对象比较大,直接加载到内存中,比较浪费资源。针对这种改进,使用了一个新的设计方法——延迟加载(Lazy-load Singleton)。

懒汉模式:

/** * 演示单例模式之懒汉模式 * @author Administrator * */public class LazySingleton {    private static LazySingleton  instance;     // 构造函数必须是私有的,不能被外部直接调用。      private LazySingleton()    {    }   // 暴露给外部,提供实例。    public   static  LazySingleton  getSingleInstance()    {        if (instance == null)        {                    instance = new LazySingleton();        }             return instance;    }  }
 这种写法就是所谓的懒汉模式。它使用了延迟加载来保证对象在没有使用之前,是不会进行初始化的。 但是,通常这个时候面试官又会提问新的问题来刁难一下。他会问:这种写法线程安全吗?回答必然是:不安全。 比如两个线程同时进入getInstance()发现instance为空,那么它们都会去执行new Singleton(), 从而导致实例不止一个。

怎么解决呢,很简单,在那个方法前面加一个同步锁Synchronized就OK了
同步的代价必然会一定程度的使程序的并发度降低,我们观察到,线程不安全的原因其实是在初始化对象的时候,所以,可以想办法把同步的粒度降低,只在初始化对象的时候进行同步。所以衍生出一个新的设计思想——双重检查锁(Double-Checked Lock)。

双重锁定:

/** * 演示单例模式之双重锁定 * @author Administrator * */public class DoubleCheckedSingleton {    private static DoubleCheckedSingleton  instance;        private DoubleCheckedSingleton()    {    }public static synchronized DoubleCheckedSingleton getSingleInstance()    {        //性能改进——双重锁定: Double-Check Locking        if(instance==null)   //  1. 先判断        {            synchronized (DoubleCheckedSingleton.class) // 2. 再同步            {                if (instance == null)  //3. 再判断                {                    instance = new DoubleCheckedSingleton(); //4. 实例化                }            }        }          return instance;    }  }

问题在哪里?假设线程A执行到调用上述getSingleInstance()方法,它判断对象为空,于是线程A执行下面初始化这个对象,但初始化是需要耗费时间的,但是这个对象的地址其实已经存在了。此时如果线程B也执行调用上述getSingleInstance()方法,它判断不为空,于是直接跳到最后,返回得到了这个对象。但是,这个对象还没有被完整的初始化!得到一个没有彻底初始化完全的对象有什么用!!
关于这个Double-Checked Lock的讨论有很多,目前公认这是一个Anti-Pattern(即:反面模式),不推荐使用!
这里又要提出一种新的模式——Initialization on Demand Holder. 这种方法使用内部类来做到延迟加载对象,在初始化这个内部类的时候,JLS(Java Language Sepcification)会保证这个类的线程安全。这种写法最大的巧妙在于,完全使用了Java虚拟机的机制进行同步保证,没有一个同步的关键字。

完美实现:

/** * 演示单例模式之完美实现 * @author Administrator * */public class Singleton   {      private static class SingletonHolder      {           public final static Singleton instance = new Singleton();      }      public static Singleton getInstance()      {           return SingletonHolder.instance;      }   } 

九、listview如何优化(这个很重要,多次被问到)

1.分页加载
2.convertView缓存
3.viewHolder
4.scrollListener,记住滑动的状态
5.setTag,getTag防止乱序

十、Activity和Fragment的生命周期

Activity:
onCreate—->onStart—>onResume—>onPause–>onStop—>onDestroy
Fragment:
onAttach–>onCreate—>onCreateView—>onActivityCreated—>
onStart—>onResume—>onPause—>onDestroyView—>onDestroy—>onDetach
这里写图片描述
这里写图片描述
最好是画成流程图。

十一、Android的数据存储有哪些方式,优缺点?

1.SharePreference
2.SQLite
3.ContentProvider
4.文件存储
5.网络存储

0 0