This will be my last try to understand what context means in Android, otherwise I will leave Android development because I don't understand why nobody can give a good answer to this. I do NOT WANT a copy paste from the Android docs that tell me that it is a interface for accessing resources. Either will I accept links to other questions because I have read them all, otherwise I wouldn't have asked.
As the documentation states it is a interface to the resources.
1st question
What is context? What does it mean that it is a interface to the resources?
2nd question
Why do we then pass this around all the time, would not every activity etc. have access to the same resources?
3rd question
Why is context needed in every friggin scenario? Such as Button myButton = new Button(this);
4th question
Yet another question about why context is passed to e.g. listadapters?
Thank you for your time:)
Would it help you to visualise a Context as a pointer to your parent object?
So, this is why in your example you create a Button with
Button myButton = new Button ( this );
The button (and Android) needs to know with which Activity it is to be associated in order to properly manage resources (as you yourself has said - don't forget, it's for Android just as much as for you or your user) and to know for example, when to trigger your onClick(). Without knowing in which Context your button exists, how does Android know whether to show it or not? How does Android know whether to send onClick() events or not? It's because it knows the context of the button.
If your buttons context is the same as the active Activity, then it's visible to the user and needs to be managed differently to an object that is not visible - for instance, the visible Activity and it's resources will be the last objects to be killed in an out-of-memory situation.
This is no different really to other operating systems and graphical toolkits, it's just different terminology.
A Context is an interface to resources, but the touchscreen is a resource, memory is a resource, the CPU is a resource - you are thinking too narrowly about what constitutes a resource (and again, it's really just semantics); resources aren't just sound files, or icons, or layouts - there are resources that Android manages too, and it needs to know the Context of your objects in order to manage those external resources properly.
Context is a means to register your objects with the system so that whenever system wants to respond to your object, it could be identified uniquely.
If you do not register your button with the system then the listener will not get the correct event and hence it will create mess and make your system crash/slow.
The concept of context is deep rooted in android. In simple terms here is my explanation:
Android is a multi-threaded platform.
There in one UI thread where everything the user sees is drawn and in the background there can be 'n' worker threads.
Every activity/service runs on its own thread.
Every activity has a local set of layouts/images/mp3's etc.
Every activity is identified in runtime by its 'Context'. Think of it as an identifier. Thus anything you might want to do within that activity you should do it with a reference of the context.
Hope this is a favorable answer for questions 1,2,3,4
1st question What is context? What
does it mean that it is a interface to
the resources?
Hmm.. Context I believe you understand that it tells you where exactly you are. As you know the concept of this pointer in Java it is same as that. The system provides each application a context. The resources needs to be mentioned that it has to be used in this context. And all these because Android is multi-threaded. It is not that you enter inside an activity and you will be dealing with just one thread.
2nd question Why do we then pass this
around all the time, would not every
activity etc. have access to the same
resources?
Well when we have one class and an inner class then if you use "this" inside the inner class then your components will take the inner class context and not the outer class context even if you meant the outer class. Here you will have to specify by saying your outer class name.this i.e you are specifying clearly that you want to use the outer class context.
Why is context needed in every friggin
scenario? Such as Button myButton = new
Button(this);
Now Button and any other widget needs to be known on which view they need to be. So by telling the context you make it clear to the widget. Say I have two classes inside a java file and now you use a button widget. How will the widget know exactly where it has to go.
I hope the answer for your forth question is also the same.
Related
I'm teaching myself how to program in Kotlin and I've run into a problem when I've tried to make a function in a class to handle some math for me.
The problem I've run into is that I don't know how to get the screen density as a var/val in the class that is out side of the MainActivity.kt
I've searched a lot for the answer and I can't seem to come up with the right term to get the resources that I need and it's driving me crazy. Every answer I've found either doesn't work or Android Studio says it's going to cause a memory leak.
I know how to get the density in the MainActivity.kt by using this code.
val scale: Float = resources.displayMetrics.density
Thanks for any help. I'm really enjoying learning Kotlin and how to make apps.
You need to access resources through a Context, as in context.resources.displayMetrics.density. An Activity is a Context, which is why you can just access resources directly (technically it's this.resources, where this is the Activity)
If you're calling that directly within an Activity, it shouldn't be a problem! If it's in another class, you'll have to get a Context from somewhere - ideally passing one in (e.g. if an Activity is calling a function, it can pass itself as a Context parameter).
There are a few things that are Contexts, but in this case specifically, you need to be careful:
After Build.VERSION_CODES#R, Resources must be obtained by Activity or Context created with Context.createWindowContext(int, Bundle). Application#getResources() may report wrong values in multi-window or on secondary displays.
Basically the Context needs to have an idea of how big the app window is, which an Activity will, but something like applicationContext might not.
The main reason to be careful is that Activities are big, so you don't want to hold onto them when they're being passed as a Context, because you might keep them in memory after the Activity has been discarded - that would be a memory leak, and it might be what you're getting warned about!
Typically if you did need to hold onto the Context for future use, you'd do something like myContext = passedContext.applicationContext - so you're not holding on to whatever object was passed in, you're plucking out the shared application context which is always in memory anyway, so it doesn't matter if you keep it. That's a safe way to store one.
But like the docs mentioned above, that's no good here, so ideally your function would:
use the Activity context to calculate whatever within the function, and use/store that value, discarding the context, or
access something within the context (resources, displayMetrics etc) and store that if you need to access it later
that way you're storing what you need to, and not holding onto the Activity when you don't need it
Contexts are weird when you're starting out, but they're basically something that provides access to information about the environment the code is running in, and system functions. And some are more specific - like an Activity is a visible component in your app, so it can provide info like the dimensions of its window, things like that.
So they're really important for Android apps, and you end up passing them around a lot (you'll see them as parameters in a lot of functions), but you also have to be careful of keeping Activitys in memory by storing references to them in components that outlive the Activity itself. Hope that makes some sense!
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!
In Android programming the single most used parameter that is passed almost everywhere is Context. And we know the purposes it serves. But we can't find out why we should pass it for those purposes, and why not accessing it from a global static place.
Based on Uncle Bob's Clean Code, one way of getting cleaner code is by reducing parameters, making them more meaningful to the task you're doing. Based on this, and based on DRYing parameters, we decided to give it a shot, and create a fully-featured application that has activities, fragments, foreground and background services, notifications, media, etc. and uses many device APIs like camera, GPS, etc. and is a real-world application, and only have one static context initialized at the application creation.
So in the application creation we created a public static Context context variable, and we initialized it using getApplicationContext() method in onCreate() override.
Then instead of passing context like this, getContext, etc. throughout code, we simply used App.context, and we didn't pass it as a constructor parameter to our adapters and other utility functions.
Now after venturing this bold movement, we don't see any problem with our app. Everything works just fine, battery consumption is not changed, at least it's not measureable to us so it's very low. Memory consumption is not changed and we can't measure it. Application performance and speed is not changed measurably.
So we have this really big question in our mind that, what are the downsides on our approach? Why Android guys don't just expose a global context that can be initialized and remove all context parameters from the entire ecosystem, only accessing that global variable anytime they need it?
Please read this blog carefully you will understand Context better.
Static variables defined at global scope of the class and so they also refereed as class member.
You can not control creation and destruction of static variable.
Usefully they have been created at program loading and destroyed
when program unload.
Since static variable are class member, all threads tries to access
them has to be manage.
If one thread change value of a static variable that can possibly
break functionality of other threads.
In my projects, I use the static application context for everything except graphics. The fact is that the application context does not contain information about the style and if you create a widget based on it, then it will have a default style.
On this moment, I have never faced the problems of this approach. Importantly, I do not write tests for my projects. But I'm sure that this will not be a problem.
I also will be very grateful if you point me to the problems of such use of the context. (except testing)
Your application doesn't break because you are using the Application Context: this may not be THE best practice, but it is generally fine.
What you are missing there is that Context is an abstract class with many different implementations (an Activity is a Context, a Service is a Context, the Application is a Context) with different properties and capabilities. The Activity has an entire graphic context associated whit it and a full view hierarchy that can occupy megabytes in memory.
One common mistake (that I did myself in my early days) was to store the Activity in a static field: this led to memory leaks by having two entire views hierarchy in memory as soon as the user puts the app in background, the Activity reaches onDestroy(...) callback and the user opens the app again.
I just wanted to know how many ways to get the context, which method used in which situation.
Which one better to use, and what is the main and key deference between them.
For Your better understands you should read android official blog. an also look at HackBod Answer.
There are some references URL which help you more about the context
What exactly does using the Application Context mean?
Difference between Activity Context and Application Context
http://android-developers.blogspot.de/2009/01/avoiding-memory-leaks.html
Thanks
Context class represents the local environment of an App, It encapsulates all the services and resources available to the app. There is a base class ApplicationContext, and sub classes for components: Activity, Service etc.
Always prefer using ApplicationContext because it is global and doesn't cause serious issues if its leaked, that is: an unused reference of it stays and is not garbage collected.
Sometimes you have to use sub components like Activity or Service as context. Use this when creating Intents, or creating UI Elements, or showing a toast etc. That is: functions that are specifically bound to these component's identity, its UI or its display window.
I have a simple app, it logs a bunch of sensor/gps data. The first activity is a mess, and way too long, so i wanted to modularize it. I want to have 3 modules now:
Main Activity
Sensor Data (Gyroscope, accelerometer, etc)
GPS Data (Position, elevation, etc)
What is the best way for me to go about modularizing this? I was trying to move some of the Sensor Data out of the original class, and then I noticed that my class needed to extend some android.content.context (such as an Activity) in order to access the sensor data properly?
Thanks for a nudge in the right direction.
From my comments on the original question...
You don't need to extend Context - you can create helper classes and simply pass the Activity Context into the class constructor or into the various methods using this from the Activity.
As long as you design your helper classes correctly then it is fine and it is something that many people do and, indeed, there are various Android classes which require a Context parameter. Avoid memory leaks and use the right Context.
Sometimes using the application Context might be better as it is persistent for the life-time of all application components. It is, however, only a partial context in that certain things won't work with it (some UI-related tasks, for example). Otherwise using the Activity Context is fine as long as nothing holds a permanent reference to it (which can cause memory leaks if the Activity is destroyed.