Context is used on several place such as in activity. But why we use context in Linear Layout? Whats the main reason to use it?
LinearLayout layout = new LinearLayout(context);
In general, the Context you hand any View in Android is almost always an Activity. Like 99.9% of the time. However, there are cases where that's not what you want to pass. Such cases are those when, perhaps you're building part of the UI away from an Activity to be dropped into place later. You might not know what activity this will be attached to.
There are good reasons to make sure it is always the activity however, as is described in this article. For example, utilizing Activity makes sure the theme remains consistent.
Since a View does not need an activity, per say, to be created, we don't need to hand the Activity. Thus, the constructor only takes Context. This is a good example of ISP (The Interface Segregation Principle), in that, we're limiting the scope of what the View can access safely (what methods it can call on Context). We also increase the flexibility of the View API, because we don't require an Activity to instantiate views.
Activity isa Context as you can see in this.
A Context lasts the entire time your app is running while an Activity stops after your Activity ends. If the Activity ends before the LinearLayout object in your code, then a memory leak will happen since there is still a reference to that Activity.
Related
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.:)
Recently I have found a way to survive configuration changes. What I do is I declare the objects I want to protect as static fields. Is this a good practice?
It's never been a good practice. In my own experience I made a music player app with full of static variables and it's ram usage rocketed to more than 75 mb which is far more than any other of it's kind. The reason is, it stores the value of variable while activity is destroyed. if you have static variable on bitmaps or any other heavy file, it makes memory leaks which is not pleasant to see by user as not all devices got enough resources (ram) to keep up with heavy usage app.
Also static variables often make NullPointerExceptions as these are used by many other activities too and having a variable null may result in total failure of app...
I advise you to store the data in a SharedPreferences and just make one static field like integer and always use that to retrieve values from SharedPrefrences, its very clean and reduces the NullPointers. Moreover just one static makes u have more control over your app... For me it saves time to change 100's of static field rather than changing 1 as it's a lot easy and memory efficient...
I hope, I may help u a little !
Not really. You can cause a memory leak, because one of your static fields can hold a reference to the current Context, which could be destroyed without the reference.
The best way to survive configuration changes is to use the recomended method - Bundles. If you have to store something bigger and/or more persistant - use files, SharedPreferences or a database.
Use static may lead to nullpointer exception. Because when configuration change the current context is destroyed and if you access those context then it throws nullPointer exception.
So sharedPreferences or database is the best option for store the data.
Hope this help :)
One of the approach to retain Activity State, especially during configuration change is to make use of Fragments.
Instead of reinitializing your activity, you can alleviate the burden by retaining a Fragment when your activity is restarted due to a configuration change.
The fragments of your activity that you have marked to retain are not destroyed by Android system, when it destroyed your activity during configuration change.
You can add such fragments to your activity to preserve stateful objects.
Compare to using "static", this Approach is what being advocated at below link:
http://developer.android.com/guide/topics/resources/runtime-changes.html
I assume you can't just put in the bundle in onSaveInstanceState for some (very good) reason. So I think you have to compare with retain fragment.
If you have a static field in your class, like:
static Object myStaticReference;
you will no more worry about all the lifecycle jungle mess with onDestroy, onCreate, onSaveInstanceState of the Activity or Fragment. This will reduce considerably the code rows and make everything just easier to debug and understand. In any case you shall not have any reference in your object to a View, Activity, Fragment, Context and the like.
If for example you have something like this:
public class MyObject {
ArrayList metaData;
Context cntx;
public MyObject(Context cntx) {
this.cntx=cntx;
}
}
Then you still are in the lifecycle jungle, and you will have to pass (and repass) the reference of the context (and any other View relations you have) any time your Activity gets recreated in onCreate and still manage with onSaveInstanceState if there is any need. So in this case it is just useless.
With retain Fragment (which I suppose should be the other way) things are different too. The retain Fragment will last even when the Activity gets recreated, but you have to manage this additional fragment (the good part is that you do not need an UI for this).
I'm a little confused about the Activity being destroyed and recreated when the user's device is rotated.
I've been reading around, and I understand the rationale for doing so (it basically 'forces' the developer to make sure they haven't 'missed' anything upon rotation/language/other changes)
I'm happy to respect best practice if it is seen as such, however it begs the question:
How do I 'remember' the state of the game/app, so that when the screen is rotated I have something from which to re-generate what the user was looking at?
From what I can see, absolutely everything is destroyed, the base class constructor runs and all variables in the Activity are 'null'.
I suspect the 'savedInstanceState' (Bundle class) is where I would collect that data, but reading around it only seems to be used for when the app is closed from lack of resources (and a few other extremely fringe cases)
Am I misinformed or misunderstanding the purpose of savedInstanceState? Is it wise to abandon best practice (letting the Activity be destroyed) if I'm mindful enough to not miss anything upon rotation? Thanks in advance for any advice.
I should note this question applies to game programming (I'm not using a layout XML)
Do you need your activity to be recreated? Is there work you want to do on rotation? savedInstanceState is where you would store data to be passed to the recreation of the Activity, but since you aren't using XML layouts you may consider just adding android:configChanges="orientation" to your activity in the manifest. This will give you manual control over what happens during rotation change.
In additional to my original comment, I would override config changes for keyboard being show as well:
android:configChanges="orientation|keyboardHidden"
If there is work you want to do on rotation change you can override onConfigChange and do anything you need there.
It's hard to say that there is a time when you should always override config changes, but I often do it when I have no dependency on resource folders that are size or orientation specific and I'm doing a lot of work that would take too much time to recreate.
There are other best practices to store data while activitiy config changes.1. Developer Doc Handling Runtime Changes2. Alex Lockwood : Handling Configuration Changes with Fragments, This will answer all your questions reagarding config change and storing data.
Impt:
Fragment file to store data. You must set setRetainInstace(true) in order to store data and retrieve while your activity config changes.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// retain this fragment
setRetainInstance(true);
}
This might not make much sense in terms of Android SDK, but, in C++ I am used to keeping my main.cpp (and specifically main() function) as a place where I declare and initialize other classes/objects, and afterwards all the things that my application does take place in those classes. I never come back and check for anything in main.cpp afterwards.
But in Java, Android SDK, you have to override dozens of methods in main activity and all of that takes place in one single file. Example:
I have a MainActivity.java and SomeTest.java files in my project, where first is default MainActivity class which extends Activity, and SomeTest.java contains class that declares and runs new Thread. I initialize SomeTest class from MainActivity.java and pass a handle of the activity to it as a parameter:
SomeTest test = new SomeTest(MainActivity.this);
And having the handle to MainActivity, I proceed doing everything from this newly created thread. When I need to update the UI I use runOnUiThread() to create and show a new ListView (for example) on my main layout. I want to get the width and height of the newly created Listview, for what I have to override onWindowFocusChanged() in my MainActivity.java and notify the thread from there, as getWidth() and getHeight() will only have values when ListView is actually displayed on the screen. For me it's not a good practice to make such connections ('callbacks', if you will) from MainActivity to that thread.
Is there a way I can keep methods like onWindowFocusChanged() within the thread and don't touch the MainActivity.java at all?
As I said, might not make much sense.
Is there a way I can keep methods like onWindowFocusChanged() within the thread and don't touch the MainActivity.java at all?
onWindowFocusChanged() is a callback method. It is called on the activity. You cannot change this.
And having the handle to MainActivity, I proceed doing everything from this newly created thread.
That's generally not a good idea. Using a background thread to, say, load some data from a file or database is perfectly reasonable (though using Loader or AsyncTask may be better). However, usually, the background thread should neither know nor care about things like "the width and height of the newly created ListView".
You are certainly welcome to migrate some logic out of the activity and into other classes. You might use particular frameworks for that, such as fragments or custom views. However, the class structure should not be driven by your threading model. For example, let's go back to your opening statement:
in C++ I am used to keeping my main.cpp (and specifically main() function) as a place where I declare and initialize other classes/objects, and afterwards all the things that my application does take place in those classes
However, in C++, you would not say that you are locked into only ever having two classes, one of which is operating on some background thread. While you may have a class or classes that happen to use a background thread (or threads), the driving force behind the class structure isn't "I have a background thread" but "I want to reuse XYZ logic" or "I wish to use a class hierarchy in support of the strategy pattern" or some such.
Personally speaking Context idea taken from Android SDK seems to be messy. What you are describing comes from too much responsibility intended for Activity. That's why you need to track a LOT of things inside single file (Activity's life cycle, getting Context instance in order to show Dialog etc.). I don't think there's perfect solution but I would recommend using:
Fragment subclasses which are helping to divide your screen (and so on logic) into seperate parts
3rd party frameworks/libraries like AndroidAnnotations, RoboGuice, Otto which are perfect tools to avoid spaghetti code
if you would like to perform some UI updates from another class, consider using an AsyncTask passing it the Views you need to update. Let me know if you need an example
I read everything and understand your statements, I can see you've been doing programming for sometime but apparently is just starting with Android, I've done a lot of embed systems before so I totally get the concept of having a software that looks like:
void run(){
object.setup();
while(true){
otherObject.run();
}
}
But there's one fundamental flaw on the you logic of your question:
Android programming is a different programming paradigm from C++ and from computer programming and you should understand its specific paradigm instead of assume what is good practice from other paradigms.
Quote from you: create and show a new ListView (for example) on my main layout. I want to get the width and height of the newly created Listview, for what I have to override onWindowFocusChanged().
From that I can see that you've really trying to do Android stuff on a way that is not recommended on an Android context. A ListView you can easily implement from the XML layout setContentView(int) and use the Activity onCreate to instantiate any threading (AsyncTaskLoader) framework to load the data in background and deliver it back to the UI.
That doesn't mean that all your code will be dumped in one file making it a mess. This little example I put you can do with Activity that implements the loader callbacks, a separate class with the loader, a separate class with the data loading work, a separate class with the data adapter, the activity is just a central piece that organise and manage those classes on the correct moment of its life-cycle and at no point you need to call onWindowFocusChanged() and still have a nicely organised code.
Apart from that please refer to CommonsWare answer as it's usually cleverly written and correct.
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.