Singleton in Android

Singleton in Android

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

Singleton with Android

Your singleton is fine. The issue is that you create the instance of class GrouseSingleton and then right after that you get the value of a which is the default value "hello" . So you need to use an interface like below to inform your activity when the value of a is fetched from server:

public interface ResultListener {
void onResultFetched(int textViewId, String txt);
}

In your Activity:

try {
grouseSingleton = GrouseSingleton.getInstance(new ResultListener () {
@Override
public void onResultFetched(int textViewId, String txt) {
TextView tv45 = findViewById(id);
tv45.setText(txt);
});
grouseSingleton.startThread();
} catch (IOException e) {
e.printStackTrace();
}

set the listener in your GrouseSingleton class:

private static ResultListener listener;
public static GrouseSingleton getInstance(ResultListener listener) throws IOException {
if (instance == null) {
instance = new GrouseSingleton();
GrouseSingleton.listener = listener;
}
return instance;
}

public void startThread() throws IOException {
new Thread() {
public void run() {
try {
grouseWeather = Jsoup.connect("https://www.grousemountain.com/current_conditions#weather").get();
runOnUiThread( new Runnable()
{
public void run()
{
a = grouseWeather.select("h3.metric").first().text();
listener.onResultFetched(txtViewId, a);
}
});

} catch (IOException e) {
e.printStackTrace();
}
}
}.start();

}

Singleton Class in Android How To Use It?

To start with, I would like to define what a singleton is. A singleton is a design pattern that restricts the instantation of a class to only one instance. Notable uses include controlling concurrency, and creating a central point of access for an application to access its data store. In android this is very conveinient as many times we need an application to be able to access a central in sync data store from across many differant activities.

Now that we have defined a singleton lets answer your questions followed by a quick example.

  • Can it be used like a global variable?

It is similar to a global variable in the sense that it is accessible from anywhere, however in a certain sense it is restricted and controlled as the instantation is performed by the singleton and not the class that is getting a instance of the singleton. Therefore it allows for a finer grained level of control then a global variable.

  • That means you can assign data to a Singleton class variable and get it in some other view?

Yes, You can use a singleton to store the model data of your application and then provider helper methods that any view in your application will be able to use to get access to the data by obtaining an instance of the object that holds the data through the singleton.

I will now post a simple implementation of a singleton that can be used a central data store.

Here is a very simple singleton that could be used to get access to a List of Customer Objects.

public class CustomerLab {
private static CustomerLab mCustLab;
public List<Customer> mCustomers = new ArrayList<Customer>();

/**
* The private constructor for the Customer List Singleton class
*/
private CustomerLab() {}

public static CustomerLab getCustLab() {
//instantiate a new CustomerLab if we didn't instantiate one yet
if (mCustLab == null) {
mCustLab = new CustomerLab();
}
return mCustLab;
}
//add methods here for insert, delete, search etc......
}

As you can see, this class has a private constructor and the only way to get an instance is throught the getCustLab() method which uses the pre instantiated object. This allows all parts of an android app to get the same object to access the data store which means that the data will be in a central location and in sync across all sections of your app.

This is the basics of what a singleton class is in android and how to apply it.

Application singleton use in Android

To make your App class singleton follow the Singleton design pattern:

public class App
{
// Create the instance
private static App instance;
public static App getInstance()
{
if (instance== null) {
synchronized(App.class) {
if (instance == null)
instance = new App();
}
}
// Return the instance
return instance;
}

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

public void initFBSdk()
{
FacebookSdk.sdkInitialize(getApplicationContext());
}
}

Then to use it in any other class:

App.getInstance().initFBSdk();

If this is what you are asking for..

Using Service as singleton in Android

Is it a bad practice to create a service that works as a singleton?

It is redundant and, in the way you suggest, not going to work from the point of view of Android Service as application component which is to perform its functionality with respect to

  • Application lifecycle that, in its turn, affected by
  • system events.

Such an intention of an application component is reached by

  • its declaration in the AndroidManifest.xml,
  • triggering it (starting / binding / registering) and
  • creating (by the system) an instance of the component within Application and "attaching" it to ApplicationThread/ActivityThread.

That said, brings to the fact that application components are tied to the Application instance hosted by OS process and can't run independently.


Regarding your approach, there are two scenarios:

1. CustomService's default constructor is private as per the pattern.

By calling getInstance() a single instance of CustomService is created. The instance is just a Java object (singleton) that has nothing in common with Android Service application component. The onStart(), onStartCommand() etc. methods will never be called by the system.

An attempt to start the "service" (declared in the manifest) with startService(Intent) will fail with IllegalAccessException: access to constructor not allowed.

2. CustomService's default constructor is public (as per the code posted).

If the service is declared in AndroidManifest and the default constructor is empty, startService() won't fail, however getInstance() will create another instance of CustomService that won't be treated as Android Service application component.

This isn't a singleton.


What would you suggest me to do? Is there a better way to re-use the service in order to have some data (for instance the mProfiles array) available from other engines and activities?

Use Service as per the documentation and pick the kind of communication you need:

  • One-way communication (Activity --> Service) - use a started Service and handle each Intent (with your data attached to it, like mProfiles in case Profile class implements Parcelable) in onStartCommand();
  • Two-way communication (Activity <-> Service) - use a bound Service and communicate via IBinder.

Finally, Service in Android is a singleton. There is only one instance of each service in the system. It starts on demand and handles all pending Intents / bound clients. Once it's done or explicitly stopped, it will be destroyed.

How to implement singleton pattern in android

Use this,

public class Singleton {

private static Singleton instance = null;

//a private constructor so no instances can be made outside this class
private Singleton() {}

//Everytime you need an instance, call this
//synchronized to make the call thread-safe
public static synchronized Singleton getInstance() {
if(instance == null)
instance = new Singleton();

return instance;
}

//Initialize this or any other variables in probably the Application class
public void init(Context context) {}

}

EDIT

Made the call to getInstance thread safe by adding synchronized as suggested by @SwederSchellens.

Android - Google's Contradiction on Singleton Pattern

Since Google is contradicting itself

No, it is not.

The quoted Lint warning is not complaining about creating singletons. It is complaining about creating singletons holding a reference to an arbitrary Context, as that could be something like an Activity. Hopefully, by changing mContext = context to mContext = context.getApplicationContext(), you will get rid of that warning (though it is possible that this still breaks Instant Run — I cannot really comment on that).

Creating singletons is fine, so long as you do so very carefully, to avoid memory leaks (e.g., holding an indefinite static reference to an Activity).

Wi-Fi Connection check using singleton class android studio

You dont have to create instance variable of context in static class instead you can directly pass context of the activity or fragment from where the connectivity method is called.

WifiConnectivity.getInstance().Connectivity(context);

Singleton class in Kotlin

Just

companion object {
val instance = UtilProject()
}

will do the job because the companion object itself is a language-level singleton.

(The instance will be created when the companion object is first called.)

-- Updated --

If you need to control when the singleton object is initialized, you can create one object for each class.

class UtilProject {
....
companion object {
val instance = UtilProject()
}
}

class AnotherClass {
...
companion object {
val instance = AnotherClass()
const val abc = "ABC"
}
}

fun main(args: Array<String>) {
val a = UtilProject.instance // UtilProject.instance will be initialized here.
val b = AnotherClass.abc // AnotherClass.instance will be initialized here because AnotherClass's companion object is instantiated.
val c = AnotherClass.instance
}

Here, AnotherClass.instance is initialized before AnotherClass.instance is actually called. It is initialized when AnotherClass's companion object is called.
To prevent it from being initialized before when it is needed, you can use like this:

class UtilProject {
....
companion object {
fun f() = ...
}
}

class AnotherClass {
...
companion object {
const val abc = "ABC"
}
}

object UtilProjectSingleton {
val instance = UtilProject()
}

object AnotherClassSingleton {
val instance = AnotherClass()
}

fun main(args: Array<String>) {
UtilProject.f()
println(AnotherClass.abc)

val a = UtilProjectSingleton.instance // UtilProjectSingleton.instance will be initialized here.
val b = AnotherClassSingleton.instance // AnotherClassSingleton.instance will be initialized here.

val c = UtilProjectSingleton.instance // c is a.
}

If you don't care when each singleton is initialized, you can also use it like this:

class UtilProject {
....
companion object {
fun f() = ...
}
}

class AnotherClass {
...
companion object {
const val abc = "ABC"
}
}

object Singletons {
val utilProject = UtilProject()
val anotherClass = AnotherClass()
}

fun main(args: Array<String>) {
val a = Singletons.utilProject
val b = Singletons.anotherClass
}

In summary,

an object or a companion object is one singleton object in Kotlin.

You can assign variables in an object or objects, and then use the variables just like they were singletons.

object or companion object is instantiated when it is first used.
vals and vars in an object are initialized when the object is first instantiated (i.e., when the object is first used).

EDIT:
William Hu said in the comment that "a companion object is when the class is loaded."



Related Topics



Leave a reply



Submit