开发者

Managing android activity stacks: How can a specific instance of an activity bring itself to the front?

开发者 https://www.devze.com 2023-03-31 05:16 出处:网络
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

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开发者_StackOverflow) 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!


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.


moveTaskToFront.invoke is only available after API 11. How to implement the same in a API level 8 application.


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号