In my android app, I have a fragment where the user can add a picture, either from gallery or from camera. I've created an alert dialog and placed it in a DialogFragment. When the user chooses an option, I call startActivityForResult. My question is, where should ideally this result be handled? (i.e. where should i place onActivityResult?) In the DialogFragment class, the host fragment, or the host activity? Does it matter?
onActivityResult() will be invoked first on the Activity. After that it will be reached out to the Fragments, if you call super.onActivityResult() in your Activity.
This is because of the modular design of Fragments. If a result comes in, the Activity handles it and the unhandled results, if any, can be reached out to the Fragments.
To answer your question: Decide where it makes sense to handle the results in respect of your app design / code. If you handle it in the Fragment and send the results back to the Activity through a callback f.e., you can handle it directly in the Activity.
You must write onActivityResult() in your HostActivity.Java as follows:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
//do something
}
Yes, it does matter; It is the activity that receives the result, based on that result you decide what actions to take further, notify your fragments or whatever is that you need.
Related
I have four activities, say A, B, C and D.
My situation is A will start the activity B by startActivityForResult.
startActivityForResult(new Intent(this,B.class),ONE);
In another situation I will start activity B with a different request code, like:
startActivityForResult(new Intent(this,B.class),TWO);
In B, I need to call C or D depending on requestCode. I.e if ONE need to start C else D.
So I need to know how to check the requestCode in the child Activity (B here).
In other words, I want to get the request code that Activity B was started with.
You can pass request code by put extra.
intent.putExtra("requestCode", requestCode);
Or if you have used startActivityForResult many times, then better than editing each, you can override the startActivityForResult in your Activity, add you code there like this
#Override
public void startActivityForResult(Intent intent, int requestCode) {
intent.putExtra("requestCode", requestCode);
super.startActivityForResult(intent, requestCode);
}
So there is no need to edit all your startActivityForResult
Hope it helped you
The request code is not passed to the started activity automatically because it doesn't (and shouldn't) need to know this value. It only needs to know what to do and not where it was started from.
Starting an activity is really just another form of calling a method. When you call a method, you receive the result synchronously (right there where you made the call). In this case you are only passing in the information that method needs to do its work. You are not telling it where you called it from.
Starting an activity is the asynchronous analog of calling a method, in which case you receive the result in the special method onActivityResult(). In this method, you need to know what to do with the result you just received and you have the request code for this.
To make it a bit clearer why it isn't a good idea to pass the request code as a parameter, consider the example activity which is showing a product you can buy. On this activity there are two buttons labeled "Buy" and "Login" (as you are currently not logged in). Pressing "Login" will start an activity named "Login" which will try to log in the user using the provided information. Pressing "Buy" will first start the very same "Login" activity and if the login was successful, start the buy activity.
Now, the "Login" button uses request code 1 to start the login activity, but the "Buy" button can't use the same request code as it will have to do something different if the login is successful. So, the "Buy" button uses request code 2.
In the "Login" activity you might receive two different request codes depending on where it was called from, but you will need to do the very same procedure.
So, if you pass in the request code as a parameter, you will end up with code that needs to do the same stuff for a couple of different request codes, like:
if (requestCode == LOGIN || requestCode == BUY) {
// ...
} else ...
You will also end up with storing the request code constants in a central location e.g. a class named RequestCodes.
In short, the request code should only be used to decide what to do with the received result. This way you will end up with a more modular, easier to maintain and easier to extend code.
I ended up using custom Intent action to pass this kind of information to the launching Activity.
protected static final String ACTION_DO_C = "do_c";
protected static final String ACTION_DO_D = "do_d";
Then you'd go like:
final Intent intent = new Intent(this,B.class)
intent.setAction(ACTION_DO_C);
startActivityForResult(intent,ONE);
And in Activity B you get the action easily:
getIntent().getAction();
You can use getCallingActivity() to get the activity that started current activity and that will receive the result value with response code at the end.
I have been making the transition from activities to activities and fragments but I am getting a little confused about how much functionality should go in the activity and how much in the fragment. My initial thought was that the activity simply loaded a fragment (and many examples online work this way). This is fine, but what happens when things get more complicated? Here is a scenario:
You have an activity that loads two fragments, but only one is showing. After clicking a button, the first fragment is hidden and the second shows. Easy enough.
Now, what about if some button on the second fragment needs to call another activity with it's own fragments? Where should the callbacks go for the button listener, in the activity or the fragment? Where should the new activity be launched from? What about if the second fragment needs to call a content provider or a service? Where should that go? What about onActivityResult?
I kind of feel that anything that crosses an activity boundary (starting new activities, getting results etc) should probably go in to the activity, but this is forcing me to bind my activity to my fragments pretty heavily with callbacks, so now I don't know. I am starting to think now that activities should ONLY handle loading and switching fragments to keep them separate, and the inter-process and inter-activity (and even inter-fragment) calls should all happen within fragments.
EDIT: I assume retaining state on an orientation change would probably play into this decision as well!
You can start Activity even Activity for result from Fragment. And also you can receive onActivityResult call in fragment. But remember, to get result from activity in fragment, in Activity you have implement onActivityResult method like this.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
Otherwise result won't get to fragment. Parameter requestCode can be used to differ result from various startActivityForResult calls.
I have discovered a very helpful site. It answers my questions and has a lot of information about Fragments and Activities and how they should relate:
http://developer.android.com/training/basics/fragments/communicating.html
My application contains four tabs at the bottom.Each tab has multiple child activities.The flow may be like this,
Tab1--A-->B-->C-->D-->E
Tab2--X-->Y-->D-->E
Tab3--M
Tab4--P-->Q-->Y-->D-->E
My question is ,
when I am in C child activity of Tab1,and I press Tab2.Again when I come back to Tab1 ,it is in C child activity.But I want A activity to be restarted.can someone please give the solution by providing some sample code.Thank in advance
from your B activity, start C activity using method, startActivityForResult() and Override onActivityResult() method in all of them this way.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
finish();
}
Now at every Tab switch, you must call finish() at current active activty. that in turn will destory all activities and coming back to that tab will show you first activity.
Note that, you wont want to destroy your first activty. For this reason, you must start activity B from A using startActivity() and you donot need to Override onActivityResult() for A activity.
regards,
Aqif Hamid
How can I pop fragment from backstack without resuming it? I just want to remove from back stack, I don't want to display it.
It's architectural question.
1)Suppose we have 2 controllers (fragments/activities): controller A and controller B.
Both of them connected to one instance of some Model (you may use binding with service, Singleton pattern or init model in Application-heir class and make a getter to it).
When something interesting happens in controller B, he notifies model about it and then model calls controllerA.finish() / controllerA.remove().
Of course, I always try to implement this solution as nicely as possible, but there is a main idea.
2)In another circumstances, I call finish() immediately after startActivity(intent);
3)Also I may write: startActivityForResult(intent, requestCode) and after finishing second activity method onActivityResult(requestCode, responseCode, intent) is called - if requestCode's are equal, I finish the activity.
If you don't use a FragmentTransaction's method public abstract FragmentTransaction addToBackStack (String name) to add it to the back stack. There will not be a need to remove it.
I have four activities, say A, B, C and D.
My situation is A will start the activity B by startActivityForResult.
startActivityForResult(new Intent(this,B.class),ONE);
In another situation I will start activity B with a different request code, like:
startActivityForResult(new Intent(this,B.class),TWO);
In B, I need to call C or D depending on requestCode. I.e if ONE need to start C else D.
So I need to know how to check the requestCode in the child Activity (B here).
In other words, I want to get the request code that Activity B was started with.
You can pass request code by put extra.
intent.putExtra("requestCode", requestCode);
Or if you have used startActivityForResult many times, then better than editing each, you can override the startActivityForResult in your Activity, add you code there like this
#Override
public void startActivityForResult(Intent intent, int requestCode) {
intent.putExtra("requestCode", requestCode);
super.startActivityForResult(intent, requestCode);
}
So there is no need to edit all your startActivityForResult
Hope it helped you
The request code is not passed to the started activity automatically because it doesn't (and shouldn't) need to know this value. It only needs to know what to do and not where it was started from.
Starting an activity is really just another form of calling a method. When you call a method, you receive the result synchronously (right there where you made the call). In this case you are only passing in the information that method needs to do its work. You are not telling it where you called it from.
Starting an activity is the asynchronous analog of calling a method, in which case you receive the result in the special method onActivityResult(). In this method, you need to know what to do with the result you just received and you have the request code for this.
To make it a bit clearer why it isn't a good idea to pass the request code as a parameter, consider the example activity which is showing a product you can buy. On this activity there are two buttons labeled "Buy" and "Login" (as you are currently not logged in). Pressing "Login" will start an activity named "Login" which will try to log in the user using the provided information. Pressing "Buy" will first start the very same "Login" activity and if the login was successful, start the buy activity.
Now, the "Login" button uses request code 1 to start the login activity, but the "Buy" button can't use the same request code as it will have to do something different if the login is successful. So, the "Buy" button uses request code 2.
In the "Login" activity you might receive two different request codes depending on where it was called from, but you will need to do the very same procedure.
So, if you pass in the request code as a parameter, you will end up with code that needs to do the same stuff for a couple of different request codes, like:
if (requestCode == LOGIN || requestCode == BUY) {
// ...
} else ...
You will also end up with storing the request code constants in a central location e.g. a class named RequestCodes.
In short, the request code should only be used to decide what to do with the received result. This way you will end up with a more modular, easier to maintain and easier to extend code.
I ended up using custom Intent action to pass this kind of information to the launching Activity.
protected static final String ACTION_DO_C = "do_c";
protected static final String ACTION_DO_D = "do_d";
Then you'd go like:
final Intent intent = new Intent(this,B.class)
intent.setAction(ACTION_DO_C);
startActivityForResult(intent,ONE);
And in Activity B you get the action easily:
getIntent().getAction();
You can use getCallingActivity() to get the activity that started current activity and that will receive the result value with response code at the end.