Can all views within an activity be assumed to have same Context? - android

I have noticed with Views in android that sometimes getContext() returns the containing activity, whilst other times it returns the application.
For the purposes of cleaning up pending remote image loads (which I am loading via an external load manager class), can I safely assume that all views on a particular Activity will share the same context? I was thinking of passing the activity object to cleanup and removing all views with a context matching that activity. I am sure it will depend on a few things to do with the way the views were created, just wondering what those are.

This actually works very well in my testing. Essentially the Context passed to the layout inflater or view constructor will be the context of the view throughout its lifetime (makes sense). The only time these will mismatch is if you use different contexts (such as the application context) to inflate some parts of your layout... the context for views inflated via the activity's setContentView() will have the Activity set as theirs.

Related

Manually setting context in Android

I am new to Android development and I made a research about Context. I understand what it is and why is usefull. But I see that android handles context for me in activities for example, I have to extends a class that inherits from context and thats it. However in some situations I have to manually add context to a thing. For example when creating a new instance of a view from kotlin. I have to pass a context to the view constructor, for example: Button(this)
Why do I have to tell a view instance that it is part of an activity explicitly?
I am defining it inside the activity after all.
I understand that context it's like a bridge between my app and external resources and system tools but setting it manually sometimes confuses me.
True, theoretically, that could have been done only when attaching the view to a parent, and then if the parent is attached to the activity root it has context, if not - when attaching a view, Android could have gone over its descendants and set their Context.
However:
It is inconvenient to implement. It's easy to have autonomous views with each already set to its context.
There are some things that are in the context and are necessary for manipulating the view. E.g. constraint system, metrics... many bits and bolts. Views also listen to events and can provide some services that require Context before they are attached to another view.
What if you have several contexts. You want to be able to choose which context to refer to. Say, you got an always-on-too floating button that is managed by some service and views managed by the activity.
It is highly recommended to peek in Android sources. You will find cool facts inside, and it's an excellent way to learn.
I found this article: https://www.101apps.co.za/index.php/articles/all-about-using-android-s-context-class.html
I think that explains very well why do we need to pass context manually to view instances.
"Passing the context to the view when it is being constructed, gives
you the flexibility to use a different context to construct the view,
as the one used by the activity, for example. This gives the view
access to resources other than those used by the activity."
Android could set context automatically but it gives you freedom to choose another one. That could be useful.
This is because there can many other parameters for this.
We set the context because we let the Button base class(or any other you're using) that the declared variable is instance of Button but not the other classes available all over!

Android app list structure, and finding Context from a Global class

I have two questions.
Suppose I'm creating an android app with three types of screens:
first, a series of 3 tabs that display information in a list. The type of information determines which tab(s) it's displayed in.
Second, a screen with in-depth detail about a selected list item.
And third, a screen where you can add a list item, which will populate the appropriate list.
What would be a good structure for this program? Right now what I have is a Global class (extends Application) that keeps track of the lists and imports them from a JSON file, an Activity (and accompanying Fragment) for each of the three screens above, and a separate Fragment for the individual tabs.
However, I'm finding that importing the JSON file in the Globals class requires Context that I can't figure out how to get. Before I go any farther, is this a good structure?
And if so, how can I get context in a Global class?
I'm working in Android Studio 3.
Application is a Context. That is, you can just use the current instance – this – wherever you need a Context. (There's no need to call getApplicationContext().)
However, the backing Context will not be properly initialized and attached yet in an Application's constructor. An Application is actually a ContextWrapper, which is a Context subclass that delegates all method calls to a Context field that is created and set by the system upon launch. This means that you cannot call any Context methods in the constructor, as it will still be null there.
As with the Activity and Service classes, though, Applications generally should not have any explicitly defined constructors anyway. Any initialization that needs to be done can be performed in its onCreate() method. The Context field will have been set by then.

Why we need to pass Context to a View?

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

When will a View method's Context param not be equivalent to .getContext()

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.

Is it safe for a view to reference the activity that's displaying it?

I have extended View and passed it an instance of my Activity so the view can access some member variables and methods.
But now I'm thinking this could be a potential memory leak, because even after the Activity is destroyed, it still has a reference to the view in a member variable, and vice versa. So the garbage collector may never clean them up.
However, I've seen in some of the Google API demos and examples cases where they have passed the Activity to the View as a listener.
This is fine, remember that any ordinary View you create programatically with its constructor takes a Context as its argument- usually the Context you give the constructor is just this, or the Activity itself. So your View already has a reference to its Activity. You can also get this inside the View class using its getContext() method.
When the Activity is destroyed, it will remain in memory until the GC can remove it. But as part of its onDestroy method, it sets the reference to any Views it contains to null, and so on down the View tree. Then the GC can safely remove all its component Views. Once that is complete, there are no references left to the Activity and another GC pass may delete it.
All the View constructors take the Context as a parameter so they already have a reference. Maybe post the code for the custom view so we can review it.

Categories

Resources