单列模式

单列模式

单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象成为系统中的唯一实例。

实现方式

饿汉式
饿汉式是典型的空间换时间,当类装载的时候就会创建类实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要再判断了,节省了运行时间。

public class SingIn{
    //在自己内部定义自己的一个实例,只供内部调用,作为抛出的对象
    private static final SingIn instance = new SingIn();
     // 私有构造方法,防止被实例化,不能被new SingIn()  
    private SingIn(){
    }
    //提供了一个供外部访问本class的静态方法,可以直接访问,即SingIn.getInstance()
    public static SingIn getInstance(){
        return instance;
    }
}

懒汉式
懒汉式是典型的时间换空间,也就是每次获取实例都会进行判断,看是否需要创建实例,浪费判断的时间。当然,如果一直没有人使用的话,那就不会创建实例,则节约内存空间。

    private static SingIn instance = null; 
    public static synchronized SingIn getInstance() { 
       if (instance == null)  
              instance = new SingIn();  
       return instance;  
    }  

从线程安全性上讲,不加同步的懒汉式是线程不安全的,比如,有两个线程,一个是线程A,一个是线程B,它们同时调用getInstance方法,那就可能导致并发问题。
饿汉式是线程安全的,因为虚拟机保证只会装载一次,在装载类的时候是不会发生并发的。
双重锁式

//将同步内容下方到if内部,提高了执行的效率,不必每次获取对象时都进行同步,只有第一次才同步,创建了以后就没必要了。 
private static volatile SingIn instance=null;
 private SingIn (){

 }
 public static  SingIn getInstance(){
    if(instance==null){
      synchronized(SingIn .class){
      if(instance==null){
        instance=new SingIn ();
       }
      }
     }
    return instance;
  }

使用”双重检查加锁”的方式来实现,就可以既实现线程安全,又能够使性能不受到很大的影响。
容器式
注册到容器, 注册到一个map中根据key获取对象

    private static Map objMap = new HashMap();
    //注册对象到map中
    public static void registerService(String key, SingIn instance) {
        if (!objMap.containsKey(key) ) {
            objMap.put(key, instance) ;
        }
    }

    // 根据key获取对象
    public static SingIn getService(String key) {
        return objMap.get(key) ;
    }

Android中的单例模式

LayoutInflater
Android中最常用的单例模式就是adapter中使用的LayoutInflater了,LayoutInflater.from(mContext)得到一个LayoutInflater

public View getView(int position, View convertView, ViewGroup parent)   
    View itemView = null;
    if (convertView == null) {
        itemView = LayoutInflater.from(mContext).inflate(mLayoutId, null);
    } else {
        itemView = convertView;
    }
    return itemView;
}

再看LayoutInflater中的实现

    public static LayoutInflater from(Context context) {
        LayoutInflater LayoutInflater =
                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (LayoutInflater == null) {
            throw new AssertionError("LayoutInflater not found.");
        }
        return LayoutInflater;
    }

而Context是抽象类,getSystemService是抽象方法,没有具体实现。
Android中Context的具体实现类包括Application,Activity, Service。LayoutInflater的Context 通常都是一个Activity。
一个Activity的入口是ActivityThread的main函数。在该main函数中创建一个新的ActivityThread对象,并且启动消息循环(UI线程),创建新的Activity、新的Context对象,然后将该Context对象传递给Activity。
先看ActivityThread的main函数

  public static void main(String[] args) {
        ...
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        ...
    }

再到ActivityThread的attach函数,具体原理分析

     private void attach(boolean system) {
        ...
        if (!system) {
            //通过Binder机制与ActivityManagerService通信,并且最终调用handleLaunchActivity函数
        }
        ...
    }
    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ...
        Activity a = performLaunchActivity(r, customIntent);
        ... 
     }

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
       ...
      Activity activity = null;
        try {
            //创建activity 
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
        } catch (Exception e) {
            ...
        }
        try {
            //获取Context对象
            if (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity);
                ...
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor);
                ...
                // 4 : 调用Activity的onCreate方法
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
        } catch (Exception e) {
            ...
        }
    }    

    private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
        ...
        ContextImpl appContext = ContextImpl.createActivityContext(
                this, r.packageInfo, displayId, r.overrideConfig);
        appContext.setOuterContext(activity);
        Context baseContext = appContext;
        ...
        return baseContext;
    }    

兜一圈了找到 Context的实现类为ComtextImpl类。再看ContextImpl。

Application类
Android系统自动会为每个程序运行时创建一个Application类的对象且只创建一个,虽然一个程序只对应一个Application,但是Application不是private的。
通常我们是不需要指定一个Application的,系统会自动帮我们创建,但是实际开发过程中都会创建自己的application,在项目启动时初始化一些工具,或者保存一些数据。

    public static Application getApplication(){
        return application;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        application = this;
        ...
    }

Editable.Factory
Editable的内部类,标准的饿汉式。
EditText View的getText返回的就是 Editable
TextView则是getEditableText返回 Editable

 public static class Factory {
        private static Editable.Factory sInstance = new Editable.Factory();

        /**
         * Returns the standard Editable Factory.
         */
        public static Editable.Factory getInstance() {
            return sInstance;
        }
    }

AccessibilityManager
一次加锁保证线程安全,这个类没用过,不知道谷歌为什么要这么写

 public static AccessibilityManager getInstance(Context context) {
        synchronized (sInstanceSync) {
            if (sInstance == null) {
               ....
                sInstance = new AccessibilityManager(context, service, userId);
            }
        }
        return sInstance;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值