单例设计模式在Android开发实际应用场景解析–activity的管理

单例设计模式在Android开发实际应用场景解析–activity的管理

Android中实际场景

常用的场景都是一些特殊的类,比如,管理类,皮肤的管理,activity的管理。

1.1 介绍

客户端调用单例类。

思路:

  1. 构造函数私有化。
  2. 通过静态方法获取单例对象。客户端调用
  3. 多线程环境下确保对象只有一个。
  4. 反序列化不能重新构造新对象。

1.1.1 懒汉模式

声明一个静态对象,第一次调用就初始化。

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

我们加上synchronized关键字,这样就可以做到线程的同步,在多线程环境下保证单例。懒汉式在第一次调用的时候才会实例化,节约资源,缺点是同步方法的调用造成资源开销。

1.1.2 DCL单例

需要时才实例化单例,保证线程安全,并且没有同步锁开销。

public class Singleton {
    
    
    private static Singleton instance;

    private Singleton() {
    
    
    }

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

getInstance()方法中我们判空两次,第一次是避免每次调用都进行同步锁,第二次是在null的条件下创建实例对象。

分析:

假设A,B两个线程执行getInstance(),instance = new Singleton();这句代码会被翻译成多条汇编指令,

  1. 分配内存。
  2. 调用构造函数。
  3. 将引用指向内存空间。

在多线程的环境下,这三个步骤的执行顺序不一样会导致DCL失效,执行顺序有可能1,2,3,或者1,3,2。在3执行完,2没执行之前,切换到B线程,这时候线程A执行了3,instance已经非空,B线程获取instance已经非空,就会出错。

1.1.3 volatile关键字

  1. 防止重排序。
  2. 线程可见性–某一个线程改变了公用对象(变量),短时间内可能是不可见的,每一个线程都有自己的缓冲区,线程工作区,
public class Singleton {
    
    
    private volatile static Singleton instance;

    private Singleton() {
    
    
    }

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

1.1.4 静态内部类

第一次加载Singleton类不会实例化对象,第一次调用getInstance才会导致被初始化,第一次调用getInstance()导致SingletonHolder加载,可以保证线程安全,对象唯一,延迟实例化。

public class Singleton {
    
    

    private Singleton() {
    
    
    }

    public static Singleton getInstance() {
    
    
        return SingletonHolder.sInstance;
    }

    private static class SingletonHolder {
    
    
        private static final Singleton sInstance = new Singleton();
    }
}

1.1.5 容器单例模式

Android系统服务用的这种

public class Singleton {
    
    
    private static Map<String, Object> mSingleton = new HashMap<>();

    static {
    
    
        mSingleton.put("activity_manager", new Singleton());
    }

    public static Object getService(String serviceName) {
    
    
        return mSingleton.get(serviceName);
    }
}

Android实际应用–Activity的管理

需求背景:当我们有很多个activity的时候,需要写一个管理类来操作它们的增删改查。

xml布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".activity.DebugActivity">

    <TextView
        android:onClick="click"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="text"
        android:textSize="30sp" />


</LinearLayout>

ActivityManager管理类

public class ActivityManager {
    
    
    private static ActivityManager mInstance;
    private Stack<Activity> mActivities;

    private ActivityManager() {
    
    
        mActivities = new Stack<>();
    }

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

    public void attach(Activity activity) {
    
    
        mActivities.add(activity);
    }

    public void detach(Activity detachActivity) {
    
    
        for (Activity activity : mActivities) {
    
    
            if (activity == detachActivity) {
    
    
                mActivities.remove(activity);
            }
        }
    }

    public void finish(Activity finishActivity) {
    
    
        for (Activity activity : mActivities) {
    
    
            if (activity == finishActivity) {
    
    
                mActivities.remove(activity);
                activity.finish();
            }
        }
    }

    public void finish(Class<? extends Activity> finishClassActivity) {
    
    
        for (Activity activity : mActivities) {
    
    
            if (activity.getClass().getCanonicalName().equals(finishClassActivity.getCanonicalName())) {
    
    
                mActivities.remove(activity);
                activity.finish();
            }
        }
    }
    public Activity currentActivity() {
    
    
        return mActivities.lastElement();
    }
}

LoginActivity

public class LoginActivity extends AppCompatActivity {
    
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ActivityManager.getInstance().attach(this);
        setTitle("我是LoginActivity");
    }

    public void click(View view) {
    
    
        Intent intent = new Intent(this, RegisterActivity.class);
        startActivity(intent);
    }

    @Override
    protected void onDestroy() {
    
    
        super.onDestroy();
        ActivityManager.getInstance().detach(this);
    }
}

RegisterActivity

public class RegisterActivity extends AppCompatActivity {
    
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ActivityManager.getInstance().attach(this);
        setTitle("我是RegisterActivity");
    }

    @Override
    protected void onDestroy() {
    
    
        super.onDestroy();
        ActivityManager.getInstance().detach(this);
    }

    public void click(View view) {
    
    
        ActivityManager.getInstance().finish(this);
        ActivityManager.getInstance().finish(LoginActivity.class);

    }
}

DebugActivity

class DebugActivity : AppCompatActivity() {
    
    
    private val TAG = javaClass.simpleName
    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        ActivityManager.getInstance().attach(this)
        title = "我是DebugActivity"
    }

    fun click(view: View) {
    
    
        val intent = Intent(this, LoginActivity::class.java)
        startActivity(intent)
    }

    override fun onDestroy() {
    
    
        super.onDestroy()
        ActivityManager.getInstance().detach(this)
    }
}

不管以哪种形式实现单例模式,
它们的核心原理都是将构造函数私有化,
并且通过静态方法获取一个唯一的实例,
在这个获取的过程中须保证线程安全、
防止反序列化导致重新生成实例对象等问题。
选择哪种实现方式取决于项目本身,
如是否是复杂的并发环境、JDK 版本是否过低、单例对象的资源消耗等。

猜你喜欢

转载自blog.csdn.net/weixin_46039528/article/details/132287718