Reputation: 11
I have a set of activities that I am navigating between, and because these activities are expensive to initialize, I would like to preserve the existing state if possible. The problem is that I might have the same activity open more than once, with a different state in each, and I didn't see a way that the standard Android flags could help me out with that situation.
Here's a visual example:
Imagine I have three activities:
A, B, C
Each of these activities can be open more than once, each one holding a different state. Not only are these activities expensive to initialize, but I'd also like to maintain the user's current state such as scroll position, selected items, etc...
Let's say that A(1) is an instance of activity A in state 1, and A(2) is an instance of activity A in state 2. A(1) and B(1) are unrelated.
I want to implement a circular navigation stack as follows:
... --> A(1) --> A(2) --> B(1) --> B(2) --> B(3) --> A(3) --> C(1) --> A(1) --> ...
Since the activities are expensive, I'd really like to just reuse the existing instances. However, I might need to keep around 2 or 3 instances of the same activity as you can see above.
Thanks!
Upvotes: 1
Views: 2556
Reputation: 117
moveTaskToFront.invoke
is only available after API 11. How to implement the same in a API level 8 application.
Upvotes: 2
Reputation: 49
Ok, so this actually is possible but you need to use reflection and the Intent.FLAG_ACTIVITY_MULTIPLE_TASK flag.
Here's how I did it:
Controller: starts activities with Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
Activities: Register themselves with the controller by passing in a unique id to identify their state, and their task id using getTaskId()
Controller: Creates an activity if the task has died (it checks with ActivityManager.getRunningTasks()). If the task is still alive, then it uses the following reflection code to bring a task to the front:
Class ActivityManagerNative = Class.forName("android.app.ActivityManagerNative");
Method getDefault = ActivityManagerNative.getMethod("getDefault", null);
Object activityManagerNative = getDefault.invoke(ActivityManagerNative, null);
Method[] methods = activityManagerNative.getClass().getMethods();
Method moveTaskToFront;
for (final Method method : methods) { if (method.getName().equals("moveTaskToFront")) { moveTaskToFront = method;}}
...
moveTaskToFront.invoke(activityManagerNative, registeredTaskId);
Animations can be controlled by calling overridePendingTransition from the activity that requested the task change.
Hope this can help someone else out there.
Upvotes: 4
Reputation: 14507
In the AndroidManifest.xml you can define for every activity of your app, how the runtime system should launch the specific activity. In your case you should define the launchMode property of your activity with the value "singleTask". Then the runtime system won't create multiple instances of the specific activity. Every time, when the specific activity should be launched, the runtime system will onvoke the onNewIntent() activity. In that method you can handling your different states of one specific activity.
Upvotes: 1
Reputation: 14600
What may work is this: Don't allow more than 1 instance of a particular activity. You do this when you declare each activity in the manifest by setting the launchMode. Then, keep track of the instance states by making an application wide object containing each activities Bundle object. When opening an activity, pass it the appropriate Bundle.
Upvotes: 0