Android面试题总结(二)

八、请写出两种单例模式

单例模式是一种常见的设计模式,在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 = null; 
    // 构造函数必须是私有的,不能被外部直接调用。  
    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;   
   }   
} 

枚举单例:
在枚举中构造方法限制为私有,在访问枚举实例时会执行构造方法,同时每个枚举实例都是 static final 类型的,也就表明只能被实例化一次。在调用构造方法时,单例被实例化。也就是说,因为 enum 中的实例被保证只能被实例化一次,所以 instance 也保证只被实例化一次。

class Resource{
}

public enum SingleTon{
	INSTANCE;
	private Resource instance();
	SingleTon(){
		instance = new Resource();
	}
	public  Resource getInstance(){
		return 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.网络存储

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值