Implementing the Singleton pattern for accessing an object anywhere - java

Currently, I have a class whose constructor takes a username, password, and Context. I would like to be able to access this object from anywhere, so I was thinking of implementing a singleton pattern.
The current constructor uses the credentials passed in to authenticate future api calls through that class. If I were to implement the singleton pattern, my first thought would to be have the getInstace() method take a username, password, etc.., but it seems wrong to have to pass that info everytime i grab an instance. Because of this I was thinking of adding some sort of .authenticate(usr, pswrd) method to be called when grabbing the first instance.
My question is, is this the correct approach? If not, what would be a good way to handle this? Heres the current code:
constructor:
public Play(String username, String password, Context context) {
api = getApi(username, password);
Intent intent = new Intent(context, MyService.class);
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
//check if first run
//if so, call api for info and store locally
//if not, update as needed
SharedPreferences pref = context.getSharedPreferences("pref", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
if (pref.getBoolean("first_run", true)) {
loadInitialData(context);
}
editor.putBoolean("first_run", false);
editor.commit();
}

Singleton pattern restricts the instantiation of a class and ensures that only one instance of the class exists in the java virtual machine. The singleton class must provide a global access point to get the instance of the class. Singleton pattern is used for logging, drivers objects, caching and thread pool
This code is not tested but should give you an idea how you can use singleton pattern while using SharedPrefrencess.
Constructor is private, So only getInstance() method can access the instance, so you will create an instance of this class if it doesn't exists or if instantiated previously use that instance
synchronization is required to make sure when multiple thread are trying to make a instance for the first time
import android.content.Context;
import android.content.SharedPreferences;
/**
* Created by Pankaj Nimgade on 23-05-2016.
*/
public class Play {
/**
* volatile keyword ensures that multiple threads handle the uniqueInstance
* variable correctly when it is being initialized to Singleton instance
*/
private volatile static Play play;
private static final String XML_FILE = "play_xml_file.xml";
private static final String KEY_DATA = "SOME_DATA_KEY";
private static final String KEY_USERNAME = "SOME_USERNAME_KEY";
private static final String KEY_PASSWORD = "SOME_PASSWORD_KEY";
private static SharedPreferences sharedPreferences;
private static SharedPreferences.Editor editor;
private Play() {
}
public static Play getInstance(Context context) {
if (play == null) {
synchronized (Play.class) {
if (play == null) {
sharedPreferences = context.getSharedPreferences(XML_FILE, Context.MODE_PRIVATE);
editor = sharedPreferences.edit();
play = new Play();
}
}
}
return play;
}
public boolean saveSomeData(String someData) {
editor.putString(KEY_DATA, someData);
return editor.commit();
}
public String readSomeData() {
return sharedPreferences.getString(KEY_DATA, "default Value");
}
public boolean saveUserNameData(String username) {
editor.putString(KEY_USERNAME, username);
return editor.commit();
}
public String readUserNameData() {
return sharedPreferences.getString(KEY_USERNAME, "default username Value");
}
public boolean savePasswordData(String password) {
editor.putString(KEY_PASSWORD, password);
return editor.commit();
}
public String readPasswordData() {
return sharedPreferences.getString(KEY_PASSWORD, "default password value");
}
}
in this above approach I am making instance creation of the class lazy, as the instance will only be created if demanded, although the code is thread safe and will work on all Java version you may want to consider different approach to implement this if you are using Java 5 and above.
https://sourcemaking.com/design_patterns/singleton/java/1
public class Singleton {
// Private constructor prevents instantiation from other classes
private Singleton() {}
/**
* SingletonHolder is loaded on the first execution of Singleton.getInstance()
* or the first access to SingletonHolder.INSTANCE, not before.
*/
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
The inner class is referenced no earlier (and therefore loaded no earlier by the class loader) than the moment that getInstance() is called. Thus, this solution is thread-safe without requiring special language constructs (i.e. volatile or synchronized).

Related

Singleton object is gone, My data is cleared

There are several activities and fragments that need access to a specific data, so i created a singleton object to store data in that. The problem is after a long time that the app is in background, that singleton object will disapear and become null, so when i open my app again the app crashes and throws null pointer exception to that object. What should I do? How should i share that data between activities and fragments?
Is it a good practice to store that data in database? Or bundle? or whatever?
This is my singleton:
public class Book {
private static Book ourInstance;
private int FLNB;
private Book() {
}
public static Book getInstance() {
if (ourInstance == null) {
ourInstance = new Book();
}
return ourInstance;
}
public void setFLNB(int FLNB) {
this.FLNB = FLNB;
}
public int getFLNB() {
return this.FLNB;
}
}
I set FLNB, and when singleton is gone, the value of FLNB is cleared and I need to access this value after re-initial singleton.

How to avoid the use of static variables?

I'm quite new to OOP concepts, and right now I am developing a small system, it has a login system. I have saved the user info in a database, and when I log in, I have made it so it retrieves and assigns the user info(name, privileges, etc) to a set of static variables in my staff class to use later. I was wondering is there a way around this, to save the variables while the program is running after log in to be used later in other forms. The reason I assigned them to static variables while the user has logged in, is so that I don't have to retrieve his user info everytime I need to use them(for example to check which form to fall back to if the user presses back and has certain privileges)
If you want this the OOP way, you would typically define a UserInfo class, which will hold the relevant information (passed in via constructor). If you need to change between different users, the most common solution would be to store the UserInfos in a container such as a HashMap, and have one of the attributes (possibly a dedicated one) act as key to the users. Later you can just get the information object for a given user.
In most cases using static variables is a mistake, not just for the clutter it causes but for the on-going pain of remembering it.
There are some generally accepted exceptions though. Loggers are acceptable when made static.
You are in need of a session static Context. I.e. a context that is static for one session (i.e. login).
class Context {
private static final Context context = new Context();
String userName;
String userPriveliges;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPriveliges() {
return userPriveliges;
}
public void setUserPriveliges(String userPriveliges) {
this.userPriveliges = userPriveliges;
}
public static Context getContext() {
return context;
}
}
One approach is to use the Singleton Pattern. This allows you to avoid static fields at the cost of a static method.
public class LoginInfo {
private String username;
private List<String> privileges;
private static INSTANCE = new LoginInfo();
private LoginInfo() {
}
public void initFromDB() {
}
// Everything else is non-static but this
public static getInstance() {
return INSTANCE;
}
}
public class Form1 {
public void doSomething() {
LoginInfo info = LoginInfo.getInstance();
}
}
public class Form2 {
public void doSomething() {
LoginInfo info = LoginInfo.getInstance();
}
}
The other approach is Dependency Inversion. In this case, the users of LoginInfo get the information from outside, somehow.
public class Form1 {
private LoginInfo loginInfo;
public Form1(LoginInfo loginInfo) {
this.loginInfo = loginInfo;
}
public void doSomething() {
}
}
public class Form2 {
private LoginInfo loginInfo;
public Form2(LoginInfo loginInfo) {
this.loginInfo = loginInfo;
}
public void doSomething() {
}
}
Somewhere else:
// The Hollywood Principle - don't call me, I'll call you
public void login() {
LoginInfo loginInfo = new LoginInfo();
form1 = new Form1(loginInfo);
form2 = new Form2(loginInfo);
}
The Dependency Inversion approach has the benefit of the nasty side effects of static variables and methods, at the cost of some wiring. There are frameworks such as Spring, CDI and Guice that help you with that part.
Also, Singletons are Pathalogical Liars.
Instead of using static use final. I mean un-initialised final. But it will work only if after logged offing you exit from application. If you are not existing after logged off then use registry to save users. Java has inbuilt registry, you can use it to save anything. It also has password protection, and you can use that registry as cookies of web applications. Here are few linksconstant-vs-staticbad design practice statichow to avoid static
You can pass variables through constructors. Otherwise you can use a singleton class. There's no other way.

Creating a SharedPreferencesUtil

This is my first time using SharedPreferences in my Android app. Since I will be using the SharedPreferences over and over again, I have created a utility class called SharedPreferencesUtil which contains a lot of static methods which allow me to access and modify the values. For example:
/**
* This method is used to add an event that the user
* is looking forward to. We use the objectId of a ParseObject
* because every object has a unique ID which helps to identify the
* event.
* #param objectId The id of the ParseObject that represents the event
*/
public static void addEventId(String objectId){
assert context != null;
prefs = context.getSharedPreferences(Fields.SHARED_PREFS_FILE, 0);
// Get a reference to the already existing set of objectIds (events)
Set<String> myEvents = prefs.getStringSet(Fields.MY_EVENTS, new HashSet<String>());
myEvents.add(objectId);
SharedPreferences.Editor editor = prefs.edit();
editor.putStringSet(Fields.MY_EVENTS, myEvents);
editor.commit();
}
I have a few of questions:
1. Is it a good decision to have a utility class SharedPreferencesUtil ?
2. Is the use of assert proper?
3. Is that how I will add a String to the set?
In general I think utility classes like this are fine. A few recommendations I'd have are:
Initialize your Context in a subclass of Application (in Application.onCreate()) and store a reference to that in your utility class. You don't have to worry about a memory leak if you ensure you only use the application context instead of an Activity context, and since SharedPreferences doesn't use any theme attributes, there's no need to use an Activity context anyway.
Check and throw an exception warning that the class hasn't been initialized yet if you try to use it without initialization. This way you don't need to worry about checking for a null context. I'll show an example below.
public final class Preferences {
private static Context sContext;
private Preferences() {
throw new AssertionError("Utility class; do not instantiate.");
}
/**
* Used to initialize a context for this utility class. Recommended
* use is to initialize this in a subclass of Application in onCreate()
*
* #param context a context for resolving SharedPreferences; this
* will be weakened to use the Application context
*/
public static void initialize(Context context) {
sContext = context.getApplicationContext();
}
private static void ensureContext() {
if (sContext == null) {
throw new IllegalStateException("Must call initialize(Context) before using methods in this class.");
}
}
private static SharedPreferences getPreferences() {
ensureContext();
return sContext.getSharedPreferences(SHARED_PREFS_FILE, 0);
}
private static SharedPreferences.Editor getEditor() {
return getPreferences().edit();
}
public static void addEventId(String eventId) {
final Set<String> events = getPreferences().getStringSet(MY_EVENTS, new HashSet<String>());
if (events.add(eventId)) {
// Only update the set if it was modified
getEditor().putStringSet(MY_EVENTS, events).apply();
}
}
public static Set<String> getEventIds() {
return getPreferences().getStringSet(MY_EVENTS, new HashSet<String>());
}
}
Basically, this avoids you having to always have a Context on hand to use SharedPreferences. Instead, it always retains a reference to the application context (provided you initialize it in Application.onCreate()).
You can check out how to use SharedPreferences properly here and check another example on the Android docs.
EDIT: As to your design question, it really shouldn't matter to have a static class or not.
Your SharedPreferences are shared throughout the app, and although you can create multiple SharedPreferences objects, they will essentially store and save to the same part of your app as if you just used one object.

Inner class within application class, is it right?

I'm working in a application which has many activities and most of the activities share more than one objects, So I created MyApplication class by extending android Application class to store selected objects to share. But I feel quit uncomfortable while accessing those objects inside provider/helper classes b'coz context is needed in providers to get instance of Application.
So I planned to create static class called SelectionProvider inside MyApplication class to store selected objects, then I can access those in static way without create instance to MyApplication.
MyApplication class with static inner class as follows
class MyApplication extends Application {
public static final String TAG = "MyApplication";
public static class SelectionProvider {
private static UserObj userObj;
private static TownObj townObj;
private static StoreObj storeObj;
public static UserObj getUserObj() {
return userObj;
}
public static setUserObj(UserObj userObj) {
this.userObj = userObj;
}
public static TownObj getTownObj() {
return townObj;
}
public static setTownObj(TownObj townObj) {
this.townObj = townObj;
}
public static StoreObj getStoreObj() {
return storeObj;
}
public static setStoreObj() {
this.storeObj = storeObj;
}
}
}
Is it right approach? if not why?
Will reside the selected objects (which are stored in inner class) in entire application life or will it destroyed anywhere?
This method or a static value elsewhere should work fine and last for the lifetime of the application as long as you don't have multiple processes running that need access to this object. If that's the case, you should use a Service to handle transactions.
I would not design it as an inner class. I would create SelectionProvider (and any other classes you need) as its own separate class, and instantiate it in your MyApplication class' onCreate method.
You should not instantiate the application object as it can be accessed at any time by calling getApplication() and casting it to your application class (e.g. (MyApplication)getApplication(); Then you can access any objects created by the class.
If data persistence is an issue with these classes, consider storing their values in SQLLite or as a Shared Preference, as Android may terminate your application at any time when it is in the background if it needs the resources.
I would create a singleton class of my own:
public class Data {
/* Start of singleton block */
private static Data data = new Data();
private Data(){
}
public static Data getInstance(){
}
/* End of singleton block */
private SelectionProvider selectionProvider;
public SelectionProvider getSelectionProvider(){
return selectionProvider;
}
/* other necessary methods (get, set) and classes below */
}
This way you can access your objects with Data.getInstance().getSelectionProvider().
This will be available during an active application, though you might want to build in some persistant storing of your data for when the user leaves the app for some time to come back later:
public SelectionProvider getSelectionProvider(){
if(selectionProvider == null)
selectionProvider = readSelectionProviderFromPersistantStorage();
return selectionProvider;
}

Is it ok to manipulate static attributes on runtime?

I am providing Settings of my JAVA project in a Prefs.java class with static attributes and static methods. But the token for OAuth2 needs to be assigned on runtime. Is this a good way to go... ?
public class Prefs {
//known before runtime
public static final String SERVER_BASE_URL ="http://api.mycompany.com/";
//needs to be set on startup through the setter method
private static String token;
public static String getToken() {
return token;
}
public static void setToken( String token ) {
Prefs.token = token;
}
public static String getXyEndpointUrl() {
return SERVER_BASE_URL + "/xy";
}
}
I would advice against such design. This type of static variables no better than global variables. This page gives a few reasons why you should avoid them. Here are a few of them.
Non-locality
No Access Control or Constraint Checking
Implicit coupling
Concurrency issues
Testing and Confinement
But the token for OAuth2 needs to be assigned on runtime. Is this a good way to go... ?
Here it really seems to me like you would want to pass such token to the constructor of the Prefs object.
Static variables are object-oriented substitutes for global variables in C. Try to avoid them whenever possible.
Many times you only need one object, in your case it's the Prefs object.
public class Prefs {
//known before runtime
public final String SERVER_BASE_URL ="http://api.mycompany.com/";
//needs to be set on startup through the setter method
private String token;
public String getToken() {
return token;
}
public void setToken( String token ) {
Prefs.token = token;
}
public String getXyEndpointUrl() {
return SERVER_BASE_URL + "/xy";
}
}
public class Program {
protected Prefs prefs;
protected Other prefsAware;
public Program() {
prefs = new Prefs();
prefsAware = new Other(prefs);
}
// or even (if you don't like constructor mediated passing of prefs)
public Prefs getPrefs() {
return prefs;
}
}
typically global configs are read from properties files at runtime. You can have varying config files for the development, QA, production environments.
The only thing you need to at least be aware of is that in a web application, if you set static variables from a web request, you could munge the data if you do not synchronize the setter. If you are only reading then you should be fine.
An alternative to what you are doing is why not inject the OAuth key into a service that handles the authentication concerns of your system? You could do what you need to do with a static resource, but in this case, but you should be aware that you don't really need a static variable to hold the key.

Categories

Resources