76

我已经按照这个链接成功地在 Android 中制作了单例类。 http://www.devahead.com/blog/2011/06/extending-the-android-application-class-and-dealing-with-singleton/

问题是我想要一个对象。就像我有 Activity A 和 Activity B。在 Activity AI 中从 Singleton 访问对象class。我使用该对象并对其进行了一些更改。

当我移动到 Activity B 并从 Singleton Class 访问对象时,它给了我初始化的对象并且不保留我在 Activity A 中所做的更改。还有其他方法可以保存更改吗?请高手帮帮我。这是MainActivity

public class MainActivity extends Activity {
    protected MyApplication app;        
    private OnClickListener btn2=new OnClickListener() {    
        @Override
        public void onClick(View arg0) {
            Intent intent=new Intent(MainActivity.this,NextActivity.class);
            startActivity(intent);              
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Get the application instance
        app = (MyApplication)getApplication();

        // Call a custom application method
        app.customAppMethod();

        // Call a custom method in MySingleton
        Singleton.getInstance().customSingletonMethod();

        Singleton.getInstance();
        // Read the value of a variable in MySingleton
        String singletonVar = Singleton.customVar;

        Log.d("Test",singletonVar);
        singletonVar="World";
        Log.d("Test",singletonVar);

        Button btn=(Button)findViewById(R.id.button1);
        btn.setOnClickListener(btn2);
    }

}

这是NextActivity

public class NextActivity extends Activity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_next);

            String singletonVar = Singleton.customVar;

            Log.d("Test",singletonVar);
        }
  }

Singleton班级

public class Singleton
{
    private static Singleton instance;

    public static String customVar="Hello";

    public static void initInstance()
    {
    if (instance == null)
    {
      // Create the instance
      instance = new Singleton();
    }
    }

    public static Singleton getInstance()
    {
     // Return the instance
     return instance;
     }

     private Singleton()
     {
     // Constructor hidden because this is a singleton
     }

     public void customSingletonMethod()
     {
     // Custom method
     }
 }

MyApplication

public class MyApplication extends Application
    {
    @Override
    public void onCreate()
    {
    super.onCreate();

     // Initialize the singletons so their instances
     // are bound to the application process.
     initSingletons();
     }

     protected void initSingletons()
     {
     // Initialize the instance of MySingleton
     Singleton.initInstance();
     }

     public void customAppMethod()
     {
     // Custom application method
    }
}

当我运行这段代码时,我得到了我已经在SingletonWorld 中初始化的 Hello,然后我将它输入了它,MainActivity并再次NextActivity在 logcat 中显示了 Hello。我希望它再次展示世界NextActivity。请帮我纠正这个问题。

4

8 回答 8

61

提示:要在 Android Studio 中创建单例类,请右键单击您的项目并打开菜单:

New -> Java Class -> Choose Singleton from dropdown menu

在此处输入图像描述

于 2015-09-04T11:21:17.303 回答
47

编辑 :

在 Android 中实现 Singleton 并不“安全”(参见此处),您应该使用专门用于这种模式的库,如Dagger或其他 DI 库来管理生命周期和注入。


你能从你的代码中发布一个例子吗?

看看这个要点:https ://gist.github.com/Akayh/5566992

它有效,但完成得非常快:

MyActivity : 首次设置单例 + 在私有构造函数中初始化 mString 属性 ("Hello") 并显示值 ("Hello")

为 mString 设置新值:“Singleton”

启动 activityB 并显示 mString 值。“单身狗”出现……

于 2013-05-13T08:51:34.897 回答
35

很简单,作为java,Android也支持单例。-

单例是四人组设计模式的一部分,它被归类为创建设计模式。

-> 静态成员:这包含单例类的实例。

-> 私有构造函数:这将阻止其他任何人实例化 Singleton 类。

-> 静态公共方法:这提供了对 Singleton 对象的全局访问点,并将实例返回给客户端调用类。

  1. 创建私有实例
  2. 创建私有构造函数
  3. 使用 Singleton 类的 getInstance()

    public class Logger{
    private static Logger   objLogger;
    private Logger(){
    
            //ToDo here
    
    }
    public static Logger getInstance()
    {
        if (objLogger == null)
       {
          objLogger = new Logger();
       }
       return objLogger;
       }
    
    }
    

虽然使用单例 -

Logger.getInstance();
于 2013-10-21T13:04:11.393 回答
21

rakesh 建议的答案很好,但仍然有一些描述,Android 中的 Singleton 与 Java 中的 Singleton 相同:Singleton 设计模式解决了所有这些问题。使用单例设计模式,您可以:

1) 确保只创建一个类的一个实例

2) 提供对对象的全局访问点

3) 未来允许多个实例而不影响单例类的客户端

一个基本的 Singleton 类示例:

public class MySingleton
{
    private static MySingleton _instance;

    private MySingleton()
    {

    }

    public static MySingleton getInstance()
    {
        if (_instance == null)
        {
            _instance = new MySingleton();
        }
        return _instance;
    }
}
于 2014-08-11T04:54:11.480 回答
15

正如@Lazy 在此答案中所述,您可以从 Android Studio 中的模板创建单例。值得注意的是,不需要检查实例是否为空,因为ourInstance首先初始化了静态变量。因此,Android Studio 创建的单例类实现就像下面的代码一样简单:

public class MySingleton {
    private static MySingleton ourInstance = new MySingleton();

    public static MySingleton getInstance() {
        return ourInstance;
    }

    private MySingleton() {
    }
}
于 2016-02-01T12:43:07.823 回答
6

您正在将单例复制customVar到一个singletonVar变量中,并且更改该变量不会影响单例中的原始值。

// This does not update singleton variable
// It just assigns value of your local variable
Log.d("Test",singletonVar);
singletonVar="World";
Log.d("Test",singletonVar);

// This actually assigns value of variable in singleton
Singleton.customVar = singletonVar;
于 2013-05-13T14:45:07.043 回答
3

我把我的 Singleton 版本放在下面:

public class SingletonDemo {
    private static SingletonDemo instance = null;
    private static Context context;

    /**
     * To initialize the class. It must be called before call the method getInstance()
     * @param ctx The Context used

     */
    public static void initialize(Context ctx) {
     context = ctx;
    }

    /**
     * Check if the class has been initialized
     * @return true  if the class has been initialized
     *         false Otherwise
     */
    public static boolean hasBeenInitialized() {
     return context != null;

    }

    /**
    * The private constructor. Here you can use the context to initialize your variables.
    */
    private SingletonDemo() {
        // Use context to initialize the variables.
    }

    /**
    * The main method used to get the instance
    */
    public static synchronized SingletonDemo getInstance() {
     if (context == null) {
      throw new IllegalArgumentException("Impossible to get the instance. This class must be initialized before");
     }

     if (instance == null) {
      instance = new SingletonDemo();
     }

     return instance;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException("Clone is not allowed.");
    }
}

请注意,方法 initialize 可以在主类(Splash)中调用,而 getInstance 方法可以从其他类中调用。当调用者类需要单例但它没有上下文时,这将解决问题。

最后,方法 hasBeenInitialized 用于检查类是否已初始化。这将避免不同的实例具有不同的上下文。

于 2014-01-03T11:42:48.457 回答
2

在 Android 中使用单例的最简洁和现代的方式就是使用名为Dagger 2的依赖注入框架。在这里,您对可以使用的可能范围进行了说明。单例是这些范围之一。依赖注入并不是那么容易,但你需要花点时间来理解它。它还使测试更容易。

于 2016-07-11T14:16:54.713 回答