I have two activities in which I need to pass an object array between them. From the main activity, I start the secondary activity with startActivityForResult(), and pass the array as a ParcelableArray in a Bundle. This works fine to get the array to the secondary activity; I can pull the array out of the Bundle and manipulate it from there.
The problem I'm having is when I want to pass the array back to the calling activity. I need it to occur when a user presses the back/return button on the device. I've tried placing the array back into a Bundle, calling setResult() from within onPause() on the secondary activity, but I'm assuming this is the incorrect location to perform the task. I've reached that conclusion as getCallingActivity() within onPause() returns null.
What's the proper way to return a Bundle to the calling activity in this situation?
Main Activity:
Bundle b = new Bundle();
b.putParcelableArray("com.whatever.data", items);
Intent folderView = new Intent(MainView.this, FolderView.class);
folderView.putExtras(b);
startActivityForResult(folderView, 1);
Secondary Activity:
protected void onPause () {
super.onPause();
Intent result = new Intent();
Bundle b = new Bundle();
b.putParcelableArray("com.whatever.data", items);
result.putExtras(b);
setResult(Activity.RESULT_OK, result);
}
IIRC, I've hooked onKeyDown() and watched for KeyEvent.BUTTON_BACK and called setResult() there. In Android 2.0, you'd hook onBackPressed() instead.
Another option (and one I use frequently when using activities) is the finish() method
Have you tried onDestroy instead of onPause? Alternatively, you could repeatedly call setResult within the second activity whenever the array is updated, as the result won't be passed back until the second activity is actually finished.
There's probably a better solution than either of those, but that's what came to mind.
Related
Assume I have a "post submission" feature on my application. There are two activities and layouts:
Main post activity
Location selection activity
How can I pass variables between them when they're already opened? I already know how when they haven't been opened. I use "singleTask" mode to prevent multiple instances.
Reason I need this is because there's a button that links to LocationSelectionActivity on the MainPostActivity. I want when someone clicked the button, select the location, then go back to the MainPostActivity without any activity restart so the filled fields will not reset.
Use onActivityResult() with startActivityForResult().
Reference: https://developer.android.com/training/basics/intents/result
You're probably looking for onNewIntent, you can override it in your Activity class and retrieve the new Intent in your onResume method.
/**
* Override super.onNewIntent() so that calls to getIntent() will return the
* latest intent that was used to start this Activity rather than the first
* intent.
*/
#Override
public void onNewIntent(Intent intent){
super.onNewIntent(intent); // Propagate.
setIntent(intent); // Passing the new intent to setIntent() means this new intent will be the one returned whenever getIntent() is called.
}
You should not use Activities for this, you are in your own "main process" so you should be using 1 Activity and 2 Fragments for this.
Then you can use locationSelectionFragment.setTargetFragment(this); in MainPostFragment before it is added to Activity's fragment transaction, this lets you use getTargetFragment() to just pass back the value:
((MainPostFragment)getTargetFragment()).giveValueBack(value);
But there are multiple other options each with their own strengths and weaknesses as described in this article.
my android app has a lot of Activities.
As of now, I am calling Finish() each time I start a new Activity.
So my previous one is completely destroyed and when user presses the back button, I finish current activity and start a new Intent of the previous activity.
This is making my app very slow because it has to run OnCreate every time I start an activity.
If I don't finish the previous activity, how can I call the previous activity without finishing this one? User will be opening the same activities bunch of times.
I also want to use .PutExtra() when they are switching between activities.
this is what I am doing now:
Intent intent = new Intent (this, typeof(AddNewActivity));
var json = JsonConvert.SerializeObject (myDataObject);
intent.PutExtra ("myDataObject", json);
StartActivity (intent);
Finish ();
So basically, my question is how can I not start a new Activity each time and still pass data between two or more activities?
Thank you.
A simple solution would be to simply not call "finish()" every time you go to a new activity. If you follow this approach, the back-button will take the user back to the existing instance of the previous activity. Thus you get to bypass onCreate and any time-consuming operations within.
As for passing data: use Intents. When launching a new activity, call startActivityForResult. This will allow you to:
Pass data to the new Activity in an Intent.
Pass data back to the original Activity when the new Activity is done.
See: http://developer.android.com/training/basics/intents/result.html
Im wondering how long does getIntent() in a Activity will be available (does not return null). So lets say I start Activity B from my Activity A and pass some extra data in the Intent.
In Activity B I will read the extra data from the intent in the activities onCreate() method.
So far so good. But how long is getIntent() available? I mean, if the user is displaying Activity B, but switchs to another App (i.e. by using the multitasking button) and after some hours the user clicks on the multitasking button again (the activity may have been destroyed in the meantime) and opens Activity B again. So Activity B onCreate() will be called to reinstantiate the Activity B. Does getIntent() now still returns the original Intent with the extra value or do I have to save the Intent extra value in Activities onSaveInstanceState() and use the Bundle in onCreate(Bundle state)?
Does getIntent() now still returns the original Intent with the extra value
Technically, it returns a copy of the Intent. Generally speaking, it should be identical to the original Intent, including all extras.
From Android doc, getIntent() return
Return the intent that started this activity.
But their are so many case where getIntent is null or extras are null. Check this link and this. Specially on device rotation or from pressing back keys.
But as its seems documentations says otherwise. Just to be in safe side, i will recommend you to do following
if (getIntent() != null && getIntent().getExtras() != null){
}
And, your activity code should prepared to handle the scenario where getIntent is null.
In my main activity I want to override the onResume method so it acts differently, depending on the activity, which was opened before.
For example: if the user creates a new Item for the listView (in the addNewItem activity), I need to reload the database to display the newItem.
But if he just switches into an activity, which doesn't change anything with the objects displayed in the main activity, the database shouldn't be reloaded and the GUI shouldn't be build again.
Therefor I need to know which activity was 'opened' before.
I hope you understand my problem.
A dirty way is to extend your application class and set an attribute lastActivity that you would set in every onResume/OnPause methods of every activities in your app. This way, when your main activity on resume is called, just read this lastActivity field to know where you come from. But I think it's the dirty way to do it :D
You can send something through in your intent when you call the Activity.
Intent myIntent = new Intent(Activity1.this,Activity2.class);
Bundle myData = new Bundle();
myData.putString("previousActivity", "Activity1");
myIntent.putExtras(myData);
startActivity(myIntent);
Then in the new Activity, you access this and compare the result:
Intent myLocalIntent = getIntent();
Bundle myBundle = myLocalIntent.getExtras();
String str1 = myBundle.getString("previousActivity");
if string.equals("Activity1"){
// do code changes for activity 1 here
}
There are slightly more refined ways of doing this (i.e passing through an int variable which corresponds to a particular Activity) but this is the most basic way.
The right way to do it, is to start every activity with startActivityForResult(intent, resultCode).
When an activity exits, it can call setResult(int) to return data back to its parent.
Link to Developers Resource
I have two Activities A1 and A2 , on firing some event i am calling A2 (through intent) from A1.
Now inside A2 i am firing some event and based on that i am calling A1 again and passing data through intent).
Now the problem is When A1 gets called from A2 with data , A1 activity load with itself with a new state but i want to maintain its old state when A1 was first loaded. indirectly i don't want to call onCreate.
so far i have tried following code in A1 activity , its a static method in A1 which load itself
public static void show(Context context , int index)
{
final Intent intent = new Intent();
intent.setAction(MC_MY_ACTION);
intent.putExtra("routeIndex", index);
context.startActivity(intent);
}
from A2 i am calling A1 as follows from onOptionsItemSelected and passing the selectedMenuIndex
A1.show(this,selectedMenuIndex);
If you want to save the state of your activity and have it persist through multiple onCreate() calls, you can use the Bundle object. You can save to the Activity's Bundle in onSaveInstanceState() and then load it back up in onCreate(). Take a look at http://developer.android.com/reference/android/app/Activity.html and http://developer.android.com/reference/android/os/Bundle.html.
If your activity has finish()'d, you're not going to avoid going through onCreate() again -- however there's no need to worry about that. Just let your onCreate() examine the contents of its intent extras, and if there are none then follow your default initialization but if there are extras, make them carry enough state data so you can be back in the previous state.