Singleton in Android

I have followed this link and successfully made singleton class in Android. http://www.devahead.com/blog/2011/06/extending-the-android-application-class-and-dealing-with-singleton/

Problem is that i want a single object. like i have Activity A and Activity B. In Activity A I access the object from Singleton class. I use the object and made some changes to it.

When I move to Activity B and access the object from Singleton Class it gave me the initialized object and does not keep the changes which i have made in Activity A. Is there any other way to save the changing? Please help me Experts. This is 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);
}


}

This is 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 Class

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
}
}

and 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
}
}

When i run this code, i get Hello which i have initialized in Singleton then World which i gave it in MainActivity and again shows Hello in NextActivity in logcat. I want it to show world again in NextActivity. Please help me to correct this.

185484 次浏览

EDIT :

The implementation of a Singleton in Android is not "safe" (see here) and you should use a library dedicated to this kind of pattern like Dagger or other DI library to manage the lifecycle and the injection.


Could you post an example from your code ?

Take a look at this gist : https://gist.github.com/Akayh/5566992

it works but it was done very quickly :

MyActivity : set the singleton for the first time + initialize mString attribute ("Hello") in private constructor and show the value ("Hello")

Set new value to mString : "Singleton"

Launch activityB and show the mString value. "Singleton" appears...

You are copying singleton's customVar into a singletonVar variable and changing that variable does not affect the original value in singleton.

// 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;

It is simple, as a java, Android also supporting singleton. -

Singleton is a part of Gang of Four design pattern and it is categorized under creational design patterns.

-> Static member : This contains the instance of the singleton class.

-> Private constructor : This will prevent anybody else to instantiate the Singleton class.

-> Static public method : This provides the global point of access to the Singleton object and returns the instance to the client calling class.

  1. create private instance
  2. create private constructor
  3. use getInstance() of Singleton class

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

while use singleton -

Logger.getInstance();

I put my version of Singleton below:

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.");
}
}

Note that the method initialize could be called in the main class(Splash) and the method getInstance could be called from other classes. This will fix the problem when the caller class requires the singleton but it does not have the context.

Finally the method hasBeenInitialized is uses to check if the class has been initialized. This will avoid that different instances have different contexts.

answer suggested by rakesh is great but still with some discription Singleton in Android is the same as Singleton in Java: The Singleton design pattern addresses all of these concerns. With the Singleton design pattern you can:

1) Ensure that only one instance of a class is created

2) Provide a global point of access to the object

3) Allow multiple instances in the future without affecting a singleton class's clients

A basic Singleton class example:

public class MySingleton
{
private static MySingleton _instance;


private MySingleton()
{


}


public static MySingleton getInstance()
{
if (_instance == null)
{
_instance = new MySingleton();
}
return _instance;
}
}

Tip: To create singleton class In Android Studio, right click in your project and open menu:

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

enter image description here

As @Lazy stated in this answer, you can create a singleton from a template in Android Studio. It is worth noting that there is no need to check if the instance is null because the static ourInstance variable is initialized first. As a result, the singleton class implementation created by Android Studio is as simple as following code:

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


public static MySingleton getInstance() {
return ourInstance;
}


private MySingleton() {
}
}

The most clean and modern way to use singletons in Android is just to use the Dependency Injection framework called Dagger 2. Here you have an explanation of possible scopes you can use. Singleton is one of these scopes. Dependency Injection is not that easy but you shall invest a bit of your time to understand it. It also makes testing easier.