Accessing another Activity's preferences - android

I have a Login Activity which stores credentials in its own SharedPreferences; then I added two getters for reading them, something like
public String getUsername() {
return getPreferences(MODE_PRIVATE).getString("#username", null);
}
but this throws a NPE when I call it like this
String mUser = (new Login()).getUsername();
It seems that the Activity cannot read its preferences after a simple contructor call, as if it were in some uncompleted state. I read lots of related topics, but wasn't able to find a solution. Basically, I need to share these credentials among activities in my application

That's not how you create Activities. When you just call new Login(), it doesn't have a correct context to access the shared preferences. You should also NEVER, EVER call new on a class that extends Activity or Service. That's not how android classes work.
You'll need a way to get a reference to the Activity.
But it sounds like your design isn't correct. You shouldn't need to get at another activity's preferences. If you do, just put it in the defaultSharedPrefernces instead.

Related

Can we usually skip using intents by using public variables in Android?

Many times we use intents to send data to a Fragment or get data back from a child. Can't we just put data in a public variable?
For example imagine if we want to get data from user from a dialog box.
I'm just talking about the "possibility". Undoubtedly, It is superior to use intents for code cleanness or safety...
you don't send intent's to fragments, if you want to use objects you need to have your object implement Parcelable then you can just send the object in the intent bundle
public class MyActivity extends Activity {
public int someValue = 1;
}
And in any fragment which has MyActivity as a host you can access ((MyActivity) getActivity()).someValue.
I think what he means is sending (local)broadcast... which is by the way the proper way of doing it according to my understanding.
Of course it is possible to have public (or even protected) fields and access them from a child-fragment with something like this:
assuming your parent activity is named "MainActivity"
((MainActivity) getActivity()).mMyPublicField
or:
((MainActivity) getActivity()).getPublicMethod()
- but I would never recommend doing this!
especially when you also start manipulating the public field you can run into ugly trouble when different threads are in play.
If something needs so be shared across the whole application, use SharedPreferences (if you want to store it for the next app session too) or as I mentioned first LocalBroadCastManager.

Using Shared Preferences in every activity

I want to have my application preferences accessible in every activity. I don't want to have to get all of the SharedPreferences in every activity. but instead get SharedPreferences once, and have a global object that has values for all these preferences, like if (AppSettings.isSoundOn()) {// do stuff} and have that object available everywhere with no ifs and buts.
I tried using static classes but you can't get Shared Preferences from a static class. Also it looks like that the class you get SharedPreferences in has to extend Activity, or it produces an error.
I'm sure there is a stupidly simple way this is usually done, as it is basic app functionality, but none of the Android development books I have actually covers how to deal with application wide preferences, and any tutorials I could find just cover setting and getting SharedPreferences which is simple, but you have to do it in every activity.
Create a class like MyApplication and extends from android.app.Application.
In there you can access the sharedpreferences.
In every Activity you can get the Application by using MyApplication app = (MyApplication)this.getApplication();
In MyApplication put a public method that gets the Sharedpreference and one that stores it.

SharedPreferences application context vs activity context

I am using several SharedPreferences to store data in my app.
Some preferences are used in a lot of activites.
I know that the SharedPreferences are internally backed by a map for fast read-access and written to sdcard when settings are changed.
I wonder which way is better if a sharedpreference is accessed by a lot of activies:
Instantiate it in every activity using the activity context.
Instantiate it in every activity, but using the application context.
Put it in e.g. the Application class and instantiate it only once there, similar to a singleton.
If I use 1. solution is there a sharedpreference object for every activity? And will the sharedpreference's internal map get destroyed when the activity is destroyed?
If I use 2. solution will there be only one instance although I call getSharedPreferences in every activity? And will the internal map be in memory as long as the application is alive?
Hopefully someone knows how Android handles it internally.
It is worth reviewing the sources that show that a Context instance (be it an Activity or an Application instance) share the same static map HashMap<String, SharedPreferencesImpl>.
So whenever you request an instance of SharedPreferences by the same name via Context.getSharedPreferences(name, mode) you get the same instance since it first checks if the map already contains SharedPreferences instance for a key (which is the passed name). Once SharedPreferences instance is loaded it will not be loaded again, but taken from the map instead.
So it actually does not matter which way you go, the important thing is to use the same name in order to get the same prefs from different parts of the application. However creating a single "access point" for the prefs could be a plus. So it could be a singleton wrapper over the prefs instantiated in Application.onCreate().
SharedPreferences are managed internally by Android as singletons. You can get as many instances as you want using:
context.getSharedPreferences(name, mode);
as long as you use the same name, you'll always get the same instance. Therefore there are no concurrency problems.
I will prefer using a singleton class for preference, initialize preference once by application context. create getter and setter(get/put) methods to add, update and delete data.
This way it will create instance once and can be more readable,reusable.
We can make a Preferences Singleton Class and make instance of that class in extended Application class with applicationContext, so we may use that object in whole application
I have made a sharedPreferenceManager Class and make a static object by providing applicationContext. Now static object can be accessible anywhere in project
public class App extends Application {
public static App myApp;
public static PreferenceManagerSignlton preferenceManagerSingleton;
#Override
public void onCreate() {
super.onCreate();
myApp = this;
preferenceManagerSingleton = new PreferenceManagerSignlton();
preferenceSingleton.initialize(getApplicationContext());
}
}
Accessing static object in project
App.myapp.PreferenceManagerSignltonz.getSavedValue();

Android: is it possible to refer to an Activity from a 2nd Activity?

This is a pretty simple question, but I have been unable to find anyway to accomplish what I am trying to do...
I want to launch a new Activity to display some complex information. Because of the complexity, it is undesirable to serialize the information into the intent's parameters. Is it possible for the the new Activity to get a reference to the launching activity, so it can call its methods?
If you use a custom application class, you can store information that will be kept between the activities.
See a tutorial here for instance.
The lifetime of an Activity cannot be depended upon. In this case, one way of sharing data is to have a singleton which holds the data to be shared between the two activities.
You can add a public static field to the first activity containing this (the first activity).
But beware that the first activity could be destroyed by Android while you are using the second activity, so you will have to implement a fallback method if the first activity is destroyed.
And don’t forget to unset the public static variable in the onDestroy() callback of the first activity or you will leak memory.
Is it possible for the the new Activity to get a reference to the launching activity, so it can call its methods?
Please do not do that. Android can and will destroy activities to free up memory.
Complex information like you describe should not be owned by an activity. It should be held in a central data model, like you would in any other application. Whether that central data model is mediated by a Service or a singleton or a custom Application object depends a bit on the type of data, caching models, risks of memory leaks, and so on.
You can make your complex objects public and static in ActivityA, and access them in ActivityB like this:
MyCustomObjectType complexFromA = ActivityA.complexObject;
this will work, however while in ActivityB, you can't always be sure that static objects from ActivityA will exist(they may be null) since Android may terminate your application.
so then maybe add some null checking:
if(null == ActivityA.complexObject) {
//go back to ActivityA, or do something else since the object isn't there
}
else {
//business as usual, access the object
MyCustomObjectType complexFromA = ActivityA.complexObject;
}
You could also use a Singleton object which extends Application. You would have the same problem when Android terminates your application. always need to check if the object actually exists. Using the Singleton extending Application approach seems to be the more organized way - but adds more complexity to implementation. just depends what you need to do and whatever works for your implementation.
You should create a separate class that both the activities can use.
public class HelperClass{
public void sharedFunction(){
//implement function here
}
}
I would recommend staying away from static variable in android. It can cause some unexpected behavior.
Use getParent() from new activity and call parent's method
Android Activity call another Activity method

Using Data Structure Objects to store data in Android

I am a newbie to android. My question is not about how to do something, but more on the idea I have in mind is optimized or not.
I am creating a Chat App. The biggest issue I was facing was storing Non persistent data, coz whenever the activity closed, all data was lost. The biggest problem was when user moved from Chat Screen (Chat Activity) to Peoples List (Peoples Activity) all data was lost again, and if user reinitited chat, he couldnt see the history.
As a workaround, I am creating a few data classes, and a service. The service stores data in the classes, whenever it receives an update from activity or the server. After that on each new activity I will just pass around this object from one activity to another and service.
I would like some recommendations in this, Is this a good way to go around? Thanks for your precious time.
If I've understood properly, you need a way to store data of variables or the content of one data structure or whatever and don't lose this data when your app change across severals activities, right? You need save state across several Activities.
First solution: in Java, one solution for this problem could be to use "static" variables. You can do it but using Android, we can use a more elegant solution.
Second and recommended solution: Associate the state with the Application Context (easy)
You should create your own subclass of android.app.Application. It will work like a singleton.
One subclass of Application inherit the properties of Application and you can access to this class wherever you want using the command "Context.getApplicationContext()". Normally you will use this class to have everthing that need a global access. Example:
class YourName_App extends Application {
private ArrayList<String> chatConversation;
public String getChatConversation(){
return this.chatConversation;
}
public void setChatConversation(ArrayList<String> chat){
this.chatConversation = chat;
}
}
And now your Chat Activity:
class Chat extends Activity {
ArrayList<String> conversation;
#Override
public void onCreate(Bundle b)
{
...
YourName_App appState = ((YourName_App) getApplicationContext());
conversation = appState.getChatConversation();
...
}
}
It is done! This is the best way to do it.
Sorry for my poor english.

Categories

Resources