What is the best way to get Context throughout an Activity? - java

I save to SharedPreferences within a single Activity several times. Each time I do reads or writes, I pass the Context. Following are the two options I am thinking about - which one is better (or is there a better way)
Everytime I need to pass context to a function in another class (for ex a class writing to my SharedPreferences), I am passing the this getActivity().getApplicationContext().
Should I just save a variable once in the onCreate() of the Activity (i.e. Context ctxt = getActivity().getApplicationContext()) and then use the variable ctxt throughout the Activity whenever I need to pass context.
Which way is technically better? Key is - should I be accessing getApplicationContext() each time. I am guessing that is slow (& unnecessary) and also probably causes crashes (I've been seeing some logs from my users that I am unable to reproduce but the stack traces always point to lines containing getApplicationContext())

The Activity itself can be used as the Context. Simply pass this. You can pass ActivityName.this inside an inner class.
getApplicationContext() returns "the context of the single, global Application object of the current process."

check this post its what you want, and you just use the Activity as Context and there is no problem calling getApplicationContext() anytime you want, you just might need to find alternatives to that and maybe use getBaseContext() or the activity itself

Related

access sharedpreferences in class without passing context

I have a SyncAdapter overloading onPerformSync. In that method, I'd like to access sharedpreferences to get and put settings. As I understand it, for that I need access to a context. The SyncAdapter onPerformSync has a bundle argument, and maybe I could send the context that way.
In a similar problem, I have another base class (not a service or activity) for which I'm also interested in using sharedPreferences. For this, I would either need to pass the context to a method in the class, or instantiate it with the context that is then saved as a private member.
In both of these cases, I understand that keeping and using a context beyond the lifecycle of the activity or service associated with the context can lead to memory leaks.
In my case, my application can begin with either a broadcastreceiver or the main activity. The broadcast receiver starts a background process, and the main activity just starts the main activity. Whichever opens first registers periodic SyncAdapter updates and opens the other class. So if I were to pass the context of the calling activity or service, what happens if either one of them then closes? The SyncAdapter or base class would use an outdated context, and...memory leak? Or would the context revert to whatever remains running?
I also saw the solution to this: (Static way to get 'Context' on Android?), but would that fix anything? I'd then have an activity context, an application context, and a service context. Same problem right? The SyncAdapter may end up holding on to a context that has closed, no?
Based on the first answer here (SharedPreferences application context vs activity context) I'm tempted to go with the application singleton listed in the previous link, but I want to make sure. Thanks
I think what you want to do is to create a Service to manage the SyncAdapter like mentioned here. That way, the Context passed to the Service should be valid while the SyncAdapter is running.
The link shows that you would pass Service.getApplicationContext() to the SyncAdapter constructor. Then you could store that Context as a field in the SyncAdapter and use it when you need to. That Context should be valid for as long as you need it.
When the app and / or the SyncAdapter get GC'd, they should build a new SyncAdapter with a new Context the next time you need it.

Accessing strings.xml from different contexts

Does it matter whether I access strings from strings.xml file from different contexts?
I accessed it in many ways such as: getApplicationContext().getString(R.string.name), this.getString(R.string.name),MainActivity.this.getApplicationContext().getString(R.string.name), or simply getString(R.string.name).
I understand that the application context lasts the whole application lifetime, but I honestly do not know when I should use it. Also, I cannot understand what is the difference between using this and MainActivity.this.
Please explain how I should access strings from both activities and Java classes.
The key argument for using the Application Context or the Activity Context is the dependency to the lifecycle of the whole App or a component (Activity in this case). If you wanna access the strings.xml it doesn't really matter which of both you use. Because you just use the Context get a reference to the ressource, which goes away when the Activity will be destroyed. A more importent case would be if you pass the Context to another class f.e. Because then there is a dependency to this specific Context and can lead to memory leaks if you don't clean it. There is a nice explanation about this with the usage of a BroadcastReceiver in the docs.
There is no difference between this and AnyClass.this because it points to the same class object. But you have to use AnyClass.this if you wanna access the outer class in an inner class. Or if you have an anonymous class and need to access fields of the outer class. You could see it as more strict because you refer to a specific class.

Is putExtra the only way of passing data to a new Activity?

I have created a SettingsActivity for my app. In this Activity I am using the SharedPreferences class to do handle the user editable preferences.
While setting up the SharedPreferences, I have to load them in the onCreate of my main activity and then again in the SettingsActivity. The probably was that both calls to the getXXXX() methods require defaults and I figured that it would not be good to hard-code the default values into both places because I would imagine it would be problematic in the future if I ever changed them.
Which is the best/most popular (or accepted standard) of doing this?
Create a global variables class in which I import into each activity and define my default constants in there?
Use putExtra and getExtra to pass the data from the main activity to the settings activity?
Any other suggestions?
I think Squonk has a good answer, but if you're looking for an alternative, consider creating a Settings class with all of your settings as members. It could have a static method like loadFromPreferences(Context) that would return a Settings object constructed from SharedPreferences, using whatever defaults you need. It could also have a saveSettings(Context) method to save your edits. Hope that helps.
Personally, in this situation, I'd put the default values in a resource file. In that way there's no need to use a global variables class or a helper class. Android resources already do that for you.
See:
Providing resources
More resource types
Instead of using a class with static values why dont you extend the Application class which will always live when the application's process lives. you can keep shared methods and variables in it
I would highly recommend opening the SharedPreference in the onCreate of both activities. Every time I've tried to use global variables, the values disappear in a way that's difficult to detect and fix. Activities are destroyed when they are closed. Services can be removed from memory at any time. The application context will be destroyed if your services are sleeping and don't have activities in memory.
That being said, putting a variable in the application context is probably the best place. Create a class that extends Application and set AndroidManifest.xml to use this. Just don't expect the value to be there if you try to use it from services or broadcast receivers.
Also, unless you're having problems with the activities loading too slowly, you're better off spending time on features than optimization.
You can declare objects as public static and reference them from another class. ActivityA:
public static int testIntegerA = 42;
Intent intentInteger = new Intent(getActivityContext(), ActivityB.class);
intentInteger.putExtra("INTENT_EXTRA", testIntegerA);
startActivity(intentInteger);
ActivityB:
public static int intentInt, staticInt;
staticInt = ActivityA.testIntegerA;
intentInt = getIntent().getExtras().getInt("INTENT_EXTRA");
Now both intentInt and staticInt equal 42;

In which cases getApplicationContext() function is used

I am following some tutorials for learning android but the problem is they do not contain all the details.
Specifically, it would be great if some light could be shed upon the use cases for getApplicationContext().
You can think of a Context as a handle to your application's resources (i.e. everything in the res folder) and to the Android runtime. Classes like Activity, Service, Application inherit from Context, among others.
Typically, you'll pass in the current Activity whenever a Context is required, since Activity inherits from Context.
You'll also find information about using getApplicationContext() instead of your activities when a Context is required. This usually is to prevent whatever code that needs the Context from unnecessarily holding a reference to your Activity, which in the worst case might preventing it from being garbage collected (passing in the Application isn't really a huge problem in that scenario, because it's expected to be around for a long time).
However, there are certain scenarios where an argument of a method is of type Context, but an Activity is actually required. Using startActivity() is one example of this I believe (correct me if I'm wrong).

Is there anything wrong with using a public static Context? ( Regarding getResources() )

Recently I ran into a problem when trying to load an bitmap outside of my main class. I found that within my main class I could pass this as a Context to any given function allowing me to call getResources() from within that function. There are a couple of things about this which don't make sense to me.
The keyword "this" simply refers to the current object the function is running in, right? If so, how can I pass my main class as a Context by using "this"? It doesn't even have a Context in it. I am using "extends Activity", but Activity doesn't seem to contain any function called getResources() in it either.
I found a workaround which allows me to do what I want a bit easier which is to declare a public static Context appContext; within my main class. Then, within onCreate() I set appContext = this; Then, from elsewhere I can call MainActivity.appContext.getResources() whenever I need it. So, I really have a few questions here.
Why are MainActivity(my main class) and appContext not essentially the same thing when appContext is set to "this" from inside MainActivity (There is no such thing as MainActivity.getResources())
Is this unsafe to do? Could this cause any potential problems in my program?
Is there a way to load images without having to use getResources()?
What is the proper way to show my code in this website? The standard I am used to ([code][/code] tags) don't seem to work properly in the preview, so I am assuming it is handled differently here. The formatting help page says to simply use four spaces, but that doesn't seem to show any difference in the preview section either.
EDIT:
I just read in another thread somebody said
now everything depends on your main activity's onCreate method having been called.
That got me thinking. Under what circumstances would onCreate not be called? It seems like if it wasn't called the program would stop working properly in many ways not related to having a static variable initialized inside it(ie. setContentView would not be called).
So assuming that there is nothing wrong with doing it this way, the only drawback I can find, is that "MainActivity.appContext.getResources()" is a lot to type to call a function. Is there any way to create a sort of alias for this? I suppose I could create a function which simply calls that, but that just seems silly.
If you look here you see that activity is a subclass of Context.
You can format code with a backtic, or just use the {} buttons on the editor. See the markdown manual for more info.

Categories