Android Intent Context Confusing - java

Can somebody explain this to me please :
Intent intent = new Intent(Context, AlarmReceiver.class);
I never understood and I seriously think I never will if somebody doesn't try to explain this to me in depth. This whole context thing is so confusing to me. Sometimes it works like this :
Intent intent = new Intent(getBaseContext(), AlarmReceiver.class);
Sometimes it wont work like that but it accepts only :
Intent intent = new Intent(context, AlarmReceiver.class);
Sometimes its :
Intent intent = new Intent(this, AlarmReceiver.class);
etc. etc. and many other.
I understand basics of context but how many are there? And why does eclipse throw me an error once and another time its fine? Why do we need to declare context sometimes? :
Context context;
I'm unable to find the right context for all situations how do I know what is the right one in every situation?

First of all, let me explain what the context is a bit better, then let's go on to how it can be used and received. Essentially, context is a reference to linking your resources to your program. Each object is given its own context, which contains the resources required to set that object up. It is required for many objects to be created, and to get program identifying information, among other purposes. This makes it invaluable to set up new views and activities, but it can also be used for other purposes. See also this answer for more information.
The context for an item can come from a variety of places. Sometimes it is stored and has to be retrieved, sometimes it is inherited. Basically, this is object oriented programming.
Just to give you a few examples:
Activity inherits context. Thus, if you are in an activity, you only need to pass itself to use the context. It also contains a pointer to getBaseContext(). You might occasionally need to reference that, if you need the entire application context, but most likely you won't for a while.
View does not inherit context. However, it does have a method getContext(). If you need to get a context from a view, this is the way to get it. This context will not be complete, but will only have the context for the contents of the View.
Fragments also do not inherit context. They contain a method getActivity(), which if the Fragment is active, will return the activity, which is the context for the Fragment.
BroadcastReceivers do not inherit context either. In fact, they do not contain context at all, but simply receive the current context when an event is received (Such as onReceive(Context context, Intent intent))

Context Capabilities
The common actions you can safely take with a given Context object depends on where it came from originally. Below is a table of the common places an application will receive a Context, and in each case what it is useful for:
An application CAN start an Activity from here, but it requires that a new task be created. This may fit specific use cases, but can create non-standard back stack behaviors in your application and is generally not recommended or considered good practice.
This is legal, but inflation will be done with the default theme for the system on which you are running, not what’s defined in your application.
Allowed if the receiver is null, which is used for obtaining the current value of a sticky broadcast, on Android 4.2 and above.
Original article here.

What i understand by means of context is environment.In simple terms context is the surroundings of anything.So when you are using any form of context you have to decide that what should be the surroundings of the things for which you are using context.
For example if you want some data or field to remain through out the application you should define it in application class.
Now when you get application context in any of your components of your application,this field that you have declared in the application class will be in your context.Hence you can access it.
Same is true for all context type.
If you ever try using alertDialog in the service component by using context "this".Try this one and i bet you will surely get exception as "this" represent environment of service when used in it.And as it is background component we can't add window in that.Hence it will tell you the bad token exception.Which means token generated for surrounding view is not proper for alertDialog to display.
Hope this gives you brief idea what you want.

Related

Preventing memory leaks in Android

Is it wise to get a reference to a Context object in every Activity where I need a Context by getting the Application context? I have learned that it can create memory leaks to throw around your Activity's context object but when you create complex Activities it seems that a Context object is almost always necessary. I was previously declaring a Context variable at the top of the Activity class and initializing it with the "this" keyword in onCreate. I already know this can be poor form, but is it ok to initialize the Context object in onCreate calling getApplicationContext()? In other words does this help solve my problem.
Also, is it better practice to limit the use of static variables? If I'm not mistaken, if I call a static method, or reference a static variable from a different Activity, won't that keep the other Activity in memory too?
There is really no need of a Context field in your Activity, as you can always get the context using getBaseContext(), getApplicationContext(), or this (since Activity itself is Context).
You might have to pass your Context to other classes if you want to keep you Activity class thin. This is perfectly ok as long as the lifecycle of those classes is the same as the lifecycle of your Activity. This means, when your Activity is destroyed, no objects should have the reference to the context you passed.
Static methods are extremely good as long as they don't refer to static fields. Use static methods if they don't have a state. Static fields are dangerous for a lot of reasons. So use them only for the right scenarios.
I think you need to understand the differences between Application Context and Activity Context, please refer to the answer here.
But is it ok to initialise the Context object in onCreate calling getApplicationContext()? In other words does this help solve my problem.
Why do you need to initialise a context object? Activity itself is already a context. For example:
Intent intent = new Intent(this, MainActivity.class);
You don't need to initialise a context from application context as the activity context has more capabilities. Please refer to this link.
Also, is it better practice to limit the use of static variables? If I'm not mistaken, if I call a static method, or reference a static variable from a different Activity, won't that keep the other Activity in memory too?
For sending a data from one activity to another activity, you might need parcelable object and bundle, or Event Bus to decouple both sender/receiver activity.
For static method, you might need to group them under a Utility class.

Why does intent requires context?

While working with different activities and starting them for results I have no choice but to use intent. Now intent requires context and that makes no sense to me. I know that context allows access to the application resources but
why do you need to know about the application resources when an intent is just a simple messenger?
Also, I am not so sure why some people create intent with the getApplicationContext() while other use this for the activity context????
Lastly, I am not so sure how the activity that calls for startActivityResult() receive a call back on the method onActivityResult() when I don't pass the "this" for the context but instead the application context. I thought that you have to use the "this" or passing in the current activity context that called startActivityResult() in order to receive a callback. That is just straight up java right? If you pass in a class then the other activity class will have a reference to your class and hence allows it to call the method in your class which is onActivityForResult(). However, this is not the case so what am I missing?
Intent itself does not need the Context. The constructor Intent#Intent(Context, Class) is just a convenience constructor, that internally uses the provided arguments to derive a ComponentName. ComponentName is in turn just a package name of your app and a class name to target. So ComponentName might be something like:
com.foo.bar/com.foo.bar.ui.activity.MyActivity
However, you can as well just use an empty constructor Intent#Intent() and provide ComponentName yourself (Intent#setComponentName(ComponentName)).
Therefore it doesn't matter if you provide your Application's or your Activity's context (the latter is just simpler to type). Also keep in mind that classes that require application context can call Context#getApplicationContext themselves, so this is not something you need to worry about.
About startActivityForResult() - Android manages internally a stack of your Activity records. Therefore it delivers the result to the previous Activity on the stack. It is the same way it knows where to return, when you click "back".
Please note it doesn't mean it maintains a stack of your Activity instances. These instances might be long gone - destroyed and garbage collected to free the memory. However the stack contains the information that allows to recreate them and to restore their state.
Intent does not need Context for itself but as you yourself pointed out that Intent is just a messenger. It also passes the current state of application/object to the newly created object so that it can understand that what exactly is going on in the application. And that is why we need to pass the context.
And, I believe that you want to ask about startActivityForResult(). Android itself takes care of the callback in the same way other callbacks are handled. You can take the example of Activity Life-cycle. Whenever it is started onCreate(), onStart(), onResume() are called itself by Android.
Not been much deep into Android development but still let me try with an explanation. So basically, context is a reference to linking your resources to your program. Each object is given its own context, which contains the resources required to set that object up. It is required for many objects to be created, and to get program identifying information, among other purposes. This makes it invaluable to set up new views and activities, but it can also be used for other purposes. See this Android Context for more information.
According to this page Activity inherits context. Thus, if you are in an activity, you only need to pass itself to use the context. It also contains a pointer to getBaseContext(). You might occasionally need to reference that, if you need the entire application context, but most likely you won't for a while.
There are ways of creating an Intent which do not require a Context. But if you want to target a specific class of a specific package, then providing a context for the target package is a ready way to do that. Refer this Context Lesson.
As explained by snctin in his answer getApplicationContext() offers application context. Basically the Application context is associated with the Application and will always be the same throughout the life cycle of your app. Also refer this post.
See Android - How to start (display) a new Activity. According to it
startActivity(new Intent(this, ProjectsActivity.class));
assumes your current class extends one of the Android Activity classes, which gives you access to the startActivity method.
According to Getting result from a activity, Starting another activity doesn't have to be one-way. You can also start another activity and receive a result back. To receive a result, call startActivityForResult() (instead of startActivity()).
For example, your app can start a camera app and receive the captured photo as a result. Or, you might start the People app in order for the user to select a contact and you'll receive the contact details as a result. This post will help you understand the same more better way.
Hope that helps. And also thanks becuase of your question I had a refresh with Android.:)

Can I and should I pass a Context to a static method outside of the UI?

I've looked around but never found a straightforward answer to this question. I'm wondering what would happen if I use a pattern that requires me to pass a Context to static methods to do things on the backend. For instance:
public static Observable<CreateThing> createNewThing(String thingName, Context context) { // Passing Context in
return RestNetworker.handleResponse(ServiceGenerator.createService(Service.class).createThing(thingName))
.doOnNext(response -> DatabaseHelper.getInstance(context).createThing(new Thing(response.getThingId(), thingName))); // context used to get instance of DatabaseHelper
}
This method makes an API call and then writes the object to the database locally after a success response. However, I need to pass a Context to create the instance of the database helper. I could alternatively pass the database helper itself, but then I'd be creating the instance (rather getting it, since it's singleton) in the Activity code and I'd rather not do that either.
My question really is: If, say, a user exits the Activity while the API call is in progress, will this Context instance get GC'd and result in an NPE when the response comes back? I've done this kind of thing before and never noticed that issue, but it really seems that there should be some consequence of doing this. I know that other developers must do some things off the UI thread that require a Context, so this should be a relatively easy question to answer.
Thanks guys! Please let me know if you need any more information to provide better context. Heh.
The rule is that you do not pass an instance of the Activity to some object that may keep a reference to it outside of the lifecycle of the Activity. This will cause a memory leak, as the GC will not be able to free the memory allocated to the Activity and the entire view tree contained within. In those instances you pass getApplicationContext().
In cases where the context will only be referenced for the duration of the method call, passing the Activity as this is fine.
In your case, it seems like DatabaseHelper may store a reference to the context, so I would use getApplicationContext() Note that you would not get NPE because the reference was GC if you passed an Activity, that doesn't make sense - if the DatabaseHelper was storing a strong reference, this could not occur (at least on the reference to the Activity itself).

Why use Intents in Android? [duplicate]

This question already has answers here:
What is an Intent in Android?
(14 answers)
Closed 9 years ago.
I still don't understand what is so special about Intents. Why not just use a new thread or just call the function? I think I got the whole idea about intents wrong. A simple code showing why Intents are better or when are needed would be great!
Intents are get widely used in android to switch from one activity to other . it is good practice to use intents . Using intents we can pass/send values from one activity to another. So it can be used as value passing mechanism. Also its syntax is very simple.so why to think about threads ?
Intents are asynchronous messages which allow application components to request functionality from other Android components. Intents allow you to interact with components from the own and other applications. For example an activity can start an external activity for taking a picture.
Intents are objects of the android.content.Intent type. Your code can send them to the Android system defining the components you are targeting. For example via the startActivity() method you can define that the intent should be used to start an activity.
An intent can contain data via a Bundle. This data can be used by the receiving component.
To start an activity use the method startActivity(intent). This method is defined on the Context object which Activity extends.
The following code demonstrates how you can start another activity via an intent.
# Start the activity connect to the
# specified class
Intent i = new Intent(this, ActivityTwo.class);
startActivity(i);
Why not just use a new thread or just call the function?
No matter what Thread you use, there would still need to be a mechanism to direct the message which is what an Intent does. It is a way to send a message. Now, it needs to be called on the UI Thread or have an appropriate Context passed because it needs this to send the message. Call what function? You are. It calls a constructor of the Intent class.
A simple code showing why Intents are better or when are needed would be great!
I don't have a simple code to compare to because I'm not sure what you want to see. No one is saying that it is better than something else. As to why Intents are used opposed to something else? I don't know...you would have to ask the developers of the Android platform. That is what they decided to use.
When they are needed is when you want to pass a message from one Activity to another or from one application to another. From the docs
An intent is an abstract description of an operation to be performed
I said "message" but the docs say "description of an operation to be performed" (I guess can mean the same thing). You can use them to start an Activity, pass data between Activities, and more such as telling the OS what to do at boot time. Why is it better? Better than what? That is what the developers decided to use so I guess you would have to ask them but maybe they didn't think it was better rather different.
while I don't have an example, Intents encourage coupling components loosely.
It negates the necessity of you building your own Observer design patterns and enables Inter/Intra-Application communication.

Changing a TextView in another class from a Service

I have two classes, one is a standard activity, the other a service. I would like the service to update a TextView (via .setText()) of the Activity on certain events that happen within the service.
I've tried to achieve this by programming something like a setter-method inside the Activity-Class, but TextViews don't accept a static-reference, and when I try invoking an instance of the Activity-class instead (via MyActivityClassName aVariable = new MyActivityClassName();), I get a NullPointer Exception, even though the View in questions is visible at the time of the call.
Could anyone tell me what I'm doing wrong :-)? It is probably more of a basic Java question than an Android-one, but since it might have to do with the nature of Android-services, I've still added the android-tag.
Thanks for your help!
I would like the service to update a
TextView (via .setText) of the
Activity on certain events that happen
within the service.
I would strongly recommend greater logical decoupling. Have the Service tell the Activity to update the TextView.
You can do that via a broadcast Intent, or by having the Activity provide a listener object that the Service calls. In either case, be sure the Activity detaches from the service (unregisters the listener or broadcast Intent receiver), lest you cause a memory leak.
And, of course, this only works if the activity is actually running.

Categories

Resources