单列模式
单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象成为系统中的唯一实例。
实现方式
饿汉式
饿汉式是典型的空间换时间,当类装载的时候就会创建类实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要再判断了,节省了运行时间。
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;
}