I sometimes inject link to LayoutInflater by Dagger, and produce it in module from Application context like this: LayoutInflater.from(application);. It reduces lines of code.
But colleges tell me that it is wrong way, and it has to be given from Activity context by LayoutInflater.from(MainActivity.this);
Is it true? Does behaviour of layout inflater depend on type of context?
Yes it is true. There's a big difference considering styles.
The LayoutInflater creates the views by calling their constructors. There it passes the context you passed to it. So if you use the application context instead of an activity context you might lack some information.
It's the same issue like using application context for creating views directly. Activities may define different styles and their contexts wrap these information.
Taking into consideration how you could get it, there's not a big difference. Internally LayoutInflater.cloneInContext(Context) is called to apply different context configurations.
Create a copy of the existing LayoutInflater object, with the copy pointing to a different Context than the original. This is used by ContextThemeWrapper to create a new LayoutInflater to go along with the new Context theme.
With the application context you don't get this.
If I understand things correctly, in case of using application context for creating LayoutInflater you have a chance to loose your Theme settings. See here for more details.
UPDATED
From source code of layout inflater:
Object[] args = mConstructorArgs;
args[1] = attrs;
constructor.setAccessible(true);
final View view = constructor.newInstance(args);
if (view instanceof ViewStub) {
// Use the same context when inflating ViewStub later.
final ViewStub viewStub = (ViewStub) view;
viewStub.setLayoutInflater(cloneInContext((Context) args[0]));
}
return view;
As you can see, your context (in your case application context) passes in constructions of View. It means that scope of your view will be application, not activity.
If we Application context means, the inflater instance exist throughout the application until the app is killed. In other case, if we use activity context the inflater instance will be removed once activity is destroyed.
you can 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 like services .
So It is best practice to use activity context when you dont need your object that will hold for long time or to global scale.
Hope it will help.
Related
Each Activity is a Context.
Each View needs a Context.
Is it correct to say that when we pass the Context to a View, we are basically adding a View to a certain Activity by passing the Context?
The context is required because it provides access to many android system resources.
It provides theme information so that the view can properly draw itself with the given theme, but also provides a way to access other types of resource.
It provides access to layout inflater which may be needed to create child views.
You can use context to access String resources (and other resources). You may need Strings to add an appropriate text label to your view.
If you need access to shared preferences, that can be accessed via a context.
It is not correct to say that you are adding a view to an activity if you have passed that activity to the view as a context. The activity is simply providing the context needed by the view.
Here is a more thorough answer explaining the purpose of a context
Have situation when you need to create components dynamically in the fragment. I also have a static functions to create a specific components that is used many times in the application.
Exist many opportunities to pass the context to the constructor.
But what is the best practice if the static function or when extends from the fragment?
I read a lot, but do not understand the entire picture. Thank you for your tips.
for example:
public void onAttach(Context context) {
fragmentContext = (FragmentActivity) context;
or
getActivity()
or
getActivity().getApplicationContext()
or
getActivity().getBaseContext()
or
getContext()
or... or.. or....
Thanks.
To create UI components, you should use Activity context. So that the Activity theme will be applied to the component. So you have 2 options in Fragment. One is saving the context at onAttach() and using that context to create components. Second one is using getActivity(). Both contexts are the host Activity context.
You should check whether the context is null, before using the context.
What is the difference between doing
LayoutInflater inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
and inflater = LayoutInflater.from(activity);
What is the difference between the inflaters
Difference is that in second example (via static method), you don't need to cast Object to LayoutInflater because it returns directly LayoutInflater instance.
First case returns generally Object that you have to explicitly cast to LayoutInflater. But result of both methods is new instance of LayoutInflater
Is up to you which method you'll pick up. I usually use LayoutInflater.from(); method and never have problems. I don't need to cast from Object and it'll make a trick.
As #CommonsWare mentioned, you can also call
getLayoutInflater()
If you are in Activity class (it's method of Activity). But when you are not in Activity you need to have Context variable and then you can call (for example from ListAdapter):
((Activity) context).getLayoutInflater();
But i think when you are not in Activity it's much easier and efficient to call LayoutInflater.from(); instead of approaches above.
If you are able to call view.getContext() to return the Activity's context under which the view instance is currently being rendered, why do some of the View family methods take a Context as a parameter?
Could this not be implicit, or are there occassions when getContext() is different from a Context passed to one of these methods?
Here is an example: http://developer.android.com/reference/android/widget/ViewAnimator.html#setInAnimation(android.content.Context, int)
Many thanks for clearing this up
view.getContext() actually return's your Activity's context, not application's. That is the reason you need to provide such context when initializing a new View.
And there's a difference between these two contexts. An Activity's context is attached to that particular activity's life-cycle. However, the application's context is referring to application's life-cycle.
For more info, read this.
I recently read some API returning IBinder, like getWindowToken() and getApplicationWindowToken(). Quoting the latter:
Retrieve a unique token identifying the top-level "real" window of the
window that this view is attached to. That is, this is like
getWindowToken(), except if the window this view in is a panel window
(attached to another containing window), then the token of the
containing window is returned instead.
Maybe this IPC mechanism has something to do with the View API. Android designers are not stupid or zealous: if they require a Context to build a View, it means that a Context is all they need, so building a View must be possible with an application context, a service context and -of course!- an activity context, but an activity is not required. The Context is just an umbrella API to retrieve resources, accessing databases, building intents and the like.
This is not the answer to your question, but maybe can serve as a helper point. I'm looking for the answer myself. Hope your question gets the attention it deserves.
can anyone explain the difference between context and views and when do we go for context or view ? In most of the program I find either context or view being passed to certain methods , what is actual need of passing context or view to methods?
This is a strange question. View describes one element of your ui. It can have onClickListeners, properties and so on. But every view is created in some context, usually Activity's context.
Context as itself is something like environment your code is executed in. It has access to ui(if it is an activity), it can contain some global data(application context), and has access to the resources(all of the contexts). Also, context allows you to perform common android operations like broadcasting intents, start activities and services.
So, views should be passed when you want to do something with a particular view.
Context is passed when you need access to resources, global data or ui context, or launch other android components.
We need to understand how View is constructed and what is Context.
View has three constructors, all of which use Context as an argument.
In Activity, if view is inflated programmatically as against in XML, view is inflated a View is by using LayoutInflater.
LayoutInflater takes Context as an argument and internally saves it in a class level field.
LayoutInfater layoutinflater = LayoutInflater.from(this);
where "this" is the Activity instance.
When inflater inflates view i.e. :
inflater.inflate(R.id.some_view, parent, null),
it is internally passing the saved context field to the constructor of View.
View always takes a Context as an argument and this is obvious because views live in some Context which is the Activity.
To answer your question, when context is needed to be passed to a method which itself is in Activity, you can write "this". If method is not in Activity, and you need to pass Context, then remember that View which has taken Context as a parameter, saves the object reference in a class level field. We can get this object reference by writing view.getContext().