What is ContextWrapper in Android? - android

This is what the documentation for ContextWrapper states:
Proxying implementation of Context that simply delegates all of its
calls to another Context. Can be subclassed to modify behavior without
changing the original Context.
I'm having a hard time understanding this, does it just implement methods of Context in another class?

This is an incredibly powerful capability. It does exactly what AtomaticallyBeyond writes, that is, it simply delegates method calls to another Context. So, you might say, big deal! But if you write another class that that extends ContextWrapper, that class can override the some of the method of the delegate context. For example, getAssets or getResources. Most applications have no need to do that, but for some more sophisticated applications, I go back to my first comment, that's an incredible powerful capability.

Related

How do I learn which Context I have to use for each situation in Android?

I'm learning Kotlin and I've already had to fill the context several times in different ways, like this, context.application, requireContext() etc.
I'm wondering if there is any way I can realize which context to use by myself instead copying them with tutorials.
There are mainly two type of context in android & both of them are provided to you as a ContextWrapper class object.
Application Context
This context is basically provided/used when you need to do some work that doesn't involves any view/UI operation (where you don't need to refer to/rely on any UI code).
This is mostly helpful when you're doing operations directly via your process that doesn't need any UI interactions like for an example, getting list of contacts via content provider.
So, you can consider this as parent of all other context you can have in your application and apparently this is consistent for your given process.
This context is retrieved via Application class of your app, or via any other activity by requesting like (activity.applicationContext).
Activity Context
This context is basically bounded/limited to given activity you're in right now. This is helpful to mainly do UI operations because, your context is part of the same UI you are in right now.
So, yes you can consider this a child context that can changes as per your activity changes. For most of the cases, it is not preferred to store & share this context across UI/Activities as it can lead to memory leaks.
This context can be retrieved once you're on any activity class via (Activity.this, this, context in fragments & custom views)
I agree personally that context has been confusing topic on Android since the beginning, but if you know C/C++ then I can relate this to 'pointers' (conceptually). Context are pointers for given activity/application class.

Android - what effect do different contexts have in code performance? [duplicate]

There has been a lot of posting about what these two contexts are.. But I'm still not getting it quite right
As I understand it so far:
Each is an instance of its class which means that some programmers recommend you to use this.getApplicationContext() as often as possible in order to not "leak" out any memory. This is because the other this (getting the Activity instance context) points to an Activity that is being destroyed each time the user tilts the phone or leave the app etc.. Which apparently the Garbage Collector (GC) doesn't catch and therefore uses too much memory..
But can anyone please come up with some really good coding examples where it would be the right thing to use this (getting the context of the current Activity instance) and the application context will be useless/wrong?
getApplicationContext() is almost always wrong. Ms. Hackborn (among others) have been very explicit that you only use getApplicationContext() when you know why you are using getApplicationContext() and only when you need to use getApplicationContext().
To be blunt, "some programmers" use getApplicationContext() (or getBaseContext(), to a lesser extent) because their Java experience is limited. They implement an inner class (e.g., an OnClickListener for a Button in an Activity) and need a Context. Rather than using MyActivity.this to get at the outer class' this, they use getApplicationContext() or getBaseContext() to get a Context object.
You only use getApplicationContext() when you know you need a Context for something that may live longer than any other likely Context you have at your disposal. Scenarios include:
Use getApplicationContext() if you need something tied to a Context that itself will have global scope. I use getApplicationContext(), for example, in WakefulIntentService, for the static WakeLock to be used for the service. Since that WakeLock is static, and I need a Context to get at PowerManager to create it, it is safest to use getApplicationContext().
Use getApplicationContext() when you bind to a Service from an Activity, if you wish to pass the ServiceConnection (i.e., the handle to the binding) between Activity instances via onRetainNonConfigurationInstance(). Android internally tracks bindings via these ServiceConnections and holds references to the Contexts that create the bindings. If you bind from the Activity, then the new Activity instance will have a reference to the ServiceConnection which has an implicit reference to the old Activity, and the old Activity cannot be garbage collected.
Some developers use custom subclasses of Application for their own global data, which they retrieve via getApplicationContext(). That's certainly possible. I prefer static data members, if for no other reason than you can only have one custom Application object. I built one app using a custom Application object and found it to be painful. Ms. Hackborn also agrees with this position.
Here are reasons why not to use getApplicationContext() wherever you go:
It's not a complete Context, supporting everything that Activity does. Various things you will try to do with this Context will fail, mostly related to the GUI.
It can create memory leaks, if the Context from getApplicationContext() holds onto something created by your calls on it that you don't clean up. With an Activity, if it holds onto something, once the Activity gets garbage collected, everything else flushes out too. The Application object remains for the lifetime of your process.
I think there's a lot of stuff that is poorly documented on the SDK site, this is one of them. The claim I'm going to make is that it seems as though it's better to default to using an application context and only use an activity context when you really need to. The only place where I've ever seen that you need an activity context is for a progress dialog. SBERG412 claims that you have to use an activity context for a toast message, yet the Android docs clearly show an application context being used. I've always used application context for toasts because of this Google example. If it's wrong to do so, then Google dropped the ball here.
Here's more to think about and review:
For a toast message, the Google Dev Guide uses the application context and explicitly say's to use it:
Toast Notifications
In the dialogs section of the Dev guide, you see that an AlertDialog.Builder uses the application context, and then the progress bar uses an activity context. This isn't explained by Google.
Dialogs
It seems like a good reason to use application context is when you want to handle configuration changes like an orientation change, and you want to retain objects which need a context like Views. If you look here: Run Time Changes
There is a caution about using an activity context, which can create a leak. This can be avoided with an application context with the views that are to be retained (at least that's my understanding). In an app I'm writing, I intend to use an application context because I'm trying to hold over some views and other things on an orientation change, and I still want the activity to be destroy and recreated on orientation changes. Thus I have to use an app context to not cause a memory leak (see Avoiding memory Leaks). To me it seems there are plenty of good reasons to use the application context instead of an activity context, and to me it almost seems like you would use it more often than an activity context. That's what many Android books I've gone through seem to do, and that's what much of the Google examples I've seen do.
The Google documentation really makes it seem like using application context is perfectly fine in most cases, and in fact appears more often than using an activity context in their examples (at least the examples I've seen). If it's really such a problem to use application context, then Google really needs to place more emphasis on this. They need to make it clear, and they need to redo some of their examples. I wouldn't blame this entirely on inexperienced developers since the authority (Google) really makes it look like it's not a problem to use application contexts.
I used this table as a guidance for when to use the different types of Context such as Application context (i.e: getApplicationContext()) and activity context , also BroadcastReceiver context:
All merits go to original author here for more info.
Which context to use?
There are two types of Context:
Application context is associated with the application and will always be same throughout the life of application -- it does not change. So if you are using Toast, you can use application context or even activity context (both) because toast can be displayed from anywhere with in your application and is not attached to a specific window. But there are many exceptions, one exception is when you need to use or pass the activity context.
Activity context is associated with to the activity and can be destroyed if the activity is destroyed -- there may be multiple activities (more than likely) with a single application. And sometimes you absolutely need the activity context handle. For example, should you launch a new activity, you need to use activity context in its Intent so that the new launching activity is connected to the current activity in terms of activity stack. However, you may use application's context too to launch a new activity but then you need to set flag Intent.FLAG_ACTIVITY_NEW_TASK in intent to treat it as a new task.
Let's consider some cases:
MainActivity.this refers to the MainActivity context which extends Activity class but the base class (activity) also extends Context class, so it can be used to offer activity context.
getBaseContext() offers activity context.
getApplication() offers application context.
getApplicationContext() also offers application context.
For more information please check this link.
I was wondering why not to use Application Context for every operation which it supports. In the end it lowers chance of memory leak and missing null check for getContext() or getActivity() (when using injected application context or acquired through static method from Application). Statements, like the one by Ms. Hackborn to use Application Context only if needed, don't seem convincing for me without an explanation why. But it seems that I have found an unswear why:
have found that there are issues on some Android version / device combinations that do not follow these rules. For instance, if I have a BroadcastReceiver that is passed a Context and I convert that Context to an Application Context and then try to call registerReceiver() on the Application Context there are many instances where this works fine, but also many instances where I get a crash because of a ReceiverCallNotAllowedException. These crashes occur on a wide range of Android versions from API 15 up to 22.
https://possiblemobile.com/2013/06/context/#comment-2443283153
Because it's not guaranteed that all operations described as supported by Application Context in the table below will work on all Android devices!
Two great examples of when you should use Activity context vs. the Application context are when displaying either a Toast message or a built-in Dialog message as using the Application context will cause an exception:
ProgressDialog.show(this, ....);
or
Toast t = Toast.makeText(this,....);
Both of these need information from the Activity context that is not provided in the Application context.
Application context live untill your application is alive only and it is not depend on Activity Life Cycle but, context keep object long-lived. If the object which you are used temporary, that time use Application Context and Activity Context is used totally oposite of Application Context.

Do I really need to pass around Context instances deep into the application?

Somewhere in the application, I need to get a localized string using the getString method for an error message. For this, I need a Context instance, gotten from for example an Activity. Is this really how this is designed? Am I really forced to pass around these objects into classes and methods or am I missing the point and is there some other way to get a string reference?
To clarify, in an Activity I have an inner AsyncTask subclass that in doInBackground instantiates a new class for some short network processing outside the UI thread. I want error messages to be localized and for that I need to pass in a Context instance (in other words, the Activity) into that class. The design of getting value resources from the XML files just seems to be a bit unintuitive. It makes me wonder why this is so coupled together with Context instances and not something static or - forgive me - a singleton, as Context implies to be the global application context and not just a part of it like an Activity.
No, you should not do this. A simple rule is; if what you need the context for is touching the UI or is only associated with the internals of the activity class, then you should use the activity context. Even then, it is important that any reference to the context does not have a lifetime which is greater than that of the activity.
The big danger of not following this is that you pass out a reference to the activity context to somewhere deeper in your code and your activity is destroyed whilst the reference you are holding is still in scope. You just leaked your activity and everything it has a reference to. I would recommend not passing the activity context outside the activity unless truly essential and even then, be very sure to control that life time.
So, it the context is needed for something which is not UI related, such as your need to get a string resource, then use the application context. Inside an activity, and where the string reference is declared in the activity, then using the activity context would be acceptable and in my opinion, preferred as you are making a conscious decision regarding scope and life time.
That said, you should ask whether this particular method is better placed in an activity. It may well not be but do ask yourself.
Finally, a small pedantic point. You do not pass objects anywhere. You pass a reference, in fact a value of a reference to the object. Everything in Java is passed by value.
You could always extend the application class. Make a static method on there for getInstace() to get the context.

Create class for reading files

I'm trying to create my own class for reading lines from a file, but that seems to be the problem.
From what I've been able to determine standard (Java) ways don't work under Android. I need to getResources() and so on.
public myInput(Context context) throws FileNotFoundException{
super();
br = new BufferedReader(new InputStreamReader(context.getResources().
openRawResource(R.raw.file)));
}
That's the constructor. I'm trying to create it like this.
public void choosePassword(Context context){
try{
myInput fromFile = new myInput(context);
} catch(Exception e){
}
}
The metod choosePassoword() is being called form my Activity class and to be honest don't know what he wants for Context. I want to give the method choosePassword() the file from which he should choose that password, that's what I want... can someone help me do just that?
An Activity is an indirect sub-class of Context so you can simply use choosePassword(this) when calling it from your Activity.
... to be honest don't know what he wants for Context
OK. This is an important thing to understand in Android. Contexts are the basis by which almost all apps interact or even have an identity. A Context essentially identifies where a Component's run instruction originated (this is an oversimplification). For an Android Component to run, it must have a Context to run in. Luckily, in most circumstances, the Context is provided for you. There are two specific types of Contexts that you will almost always have access to:
Every Activity is a Context. This one is subject to Lifecycle method calls.
Every Application is a Context. This one is outside of the Lifecycle and is initialized before any other Component of the Application is even created.
Both of these may be used whereever you may need a Context. If you need the Application Context, you may get it from nearly any component with the getApplication() method.
For Your Purposes
This makes your calls quite easy. If all of the calls are made from your Activity, then you may supply this as your argument. Even better, if the methods themselves are part of your Activity, you need not necessarily pass the Context as an argument and again, simply use this.
Of Important Note
You will learn that sometimes, it is easier to get one Context or another. You will also learn that sometimes while it may be more difficult, it is safer to use one Context over the other. For this, I would recommend reading up on the Lifecycle of an Activity. Not using the right one can result in memory leaks and unsafe execution. In general, if you need a Context for data or execution that only survives the Lifecycle, you can use an Activity. If you need a Context for data or execution that occurs outside the Lifecycle, use the Application.
Anyhow, didn't mean to write a book. There is a wealth of information on Contexts, how to use them and which to use. Certainly read up on it. It will make your life a ton easier.
Hope this helps,
FuzzicalLogic

Can anyone explain the difference between passing the activity context to an inner class and just referencing it with MyActivity.this?

And which way is better?
Let me know if the question needs clarification.
For reusing passing the context is easier as you then can simply copy it to another project. Otherwise you have to change all the MyActivity.this to OtherProjectActivity.this.
But most of all it doesn't matter what you use
I have chosen to answer my own question, not because any of the answers are bad, but because while they are equally good, none provide a complete answer.
It seems that one of the main factors to take into consideration is reusability:
Using MyActivity.this to refer to the context means that you will have to modify your code if you ever decide to use the class in another project/class/context.
Passing the context in the constructor and referencing it as a private variable, allows you to reuse the class wherever you want without modifications.
Another factor that will influence your choice is whether your inner class is public or it is private. It doesn't make sense to make an inner class public and then reference the context with MyActivity.this. The application would force close the moment you use the class from another activity. I would argue though, that a public class belongs in its own file, but that is up to the individual developer.
Lastly there is the matter of simplicity, as it is simpler to write MyActivity.this than to implement a constructor etc. This seeming simplicity can come back and bite you, as you can see above, if you decide you need to use the class somewhere else.
I will continue to use MyActivity.this out of simplicity for all inline eventhandlers, but for any other situation it seems that passing the context to the constructor is best practice.
This is more of a design issue as having a reference either way will have the same result. Consider the complexity, the access level and other design elements related to the inner class.

Categories

Resources