Domanda

I have an application that is already implemented. In this app. user can start any activity from any other activity.

What I want to do:

If the activity that asked to be launched is already exist in the history stack. that activity on the stack should be restarted and all the activities that exists before it in the stack should be finished.

ex: A->B->C->D->E->F now we want to start D. A B C D should be finished and a new instance of D should be started keeping on the stack E->F->D

Thanks,

È stato utile?

Soluzione 4

I would also recommend Fragment on this requirement , but since your application is already implemented, you can go with this approach.

 all the activities that exists before it in the stack should be finished.

Android doesn't provide any flag to clear all the below Activities like clearing top Activities using clearTop. It would be simple if we had clearBottom :)

Ok. If your targeting Android API version from 16, this approach will help in an optimized way. For the other lower version you need to finish each Activity individually.

Create a BaseActivity which will add all the Activity Instance into a HashMap(similar to adding Fragments to back Stack). But here this is to just remember the Activities in stack. You can also check the Activities in stack using ActivityManager.RunningTaskInfo but I don't want to make it more complex.

Declare a static variable. I prefer to do in my Application class.

 public class MyApp extends Application {
    public static HashMap<String , CommonActivity > mBackStackActivities
                   = new HashMap<String, CommonActivity>();
  }

Now, when an Activity created add its instance to the HashMap

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    MyApp.mBackStackActivities.put(getComponentName().getClassName(), this);
}

And,remove it when the Activity destroy

@Override
protected void onDestroy(){
    MyApp.mBackStackActivities.remove(getComponentName().getClassName());
    super.onDestroy();
}

Now, Override the startActivity method in base Activity class and when an Activity is startedcheck if theActivityexists inHashMap. If existsfinishall the belowActivityusingfinishAffinity`.

 @Override
public void startActivity(Intent intent) {
    if(MyApp.mBackStackActivities
        .containsKey(intent.getComponent().getClassName())){
        if(android.os.Build.VERSION.SDK_INT >= 16) {
            Activity activity = MyApp.mBackStackActivities.get(intent.getComponent().getClassName());
            // finish the activity as well as all the below Activities.
            activity.finishAffinity(); // supported from API 16
        }else {
            // loop through all the below activity and finish it
        }
    }
    super.startActivity(intent);
}

Finally, If you need to set android:taskAffinity in manifest for the required Activities, by default all the Activities will have same Affinity name (the package name). You can leave this if you want all your Activities to be covered.

    <activity
        android:name="com.example.app.activities.MainActivity"
        android:label="@string/title_activity_common"
        android:taskAffinity="@string/task_affinity_name">
    </activity>

In string xml

<string name="task_affinity_name">com.example.app.affinity</string>

Note : As said above for lower version , you need to finish each Activity Individually`

Find the complete source here https://gist.github.com/androidbensin/7d9261fd148c15575dd1

Altri suggerimenti

For this exactly you have fragments:

And I would also like recommending using navigation drawer implementation.

For navigation drawer : Navigation drawer link

Fragments example:

Fragments in android developers

Why not use fragments instead of activities?

I worked on the Tooleap SDK, and I also needed to manage several activities at once. Here is something similar to what I did. You can create you own Activity manager class. Every time your activity starts, it registers with your activity manager like this:

public class ActivityA extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        myActivityManager.register(this)
    }
}

Your activity manager class will save an array of all your started activities, and call finish to every activity previously called, and remove them from the array. Note that you should hold WeakReferences to your Activity classes, to prevent context leaks.

public class MyActivityManager {
static List<WeakReference<Activity>> sManagedActivityInstances = new ArrayList<WeakReference<Activity>>();

    static void register(Activity activity) {

        if (isActivityContainedInList()) {

            for (Iterator<WeakReference<Activity>> iterator = sManagedActivityInstances.iterator(); iterator.hasNext(); )
            {
               WeakReference<Activity> activityWeakRef = iterator.next();
               if (isSameActivity(activity, activityWeakRef))
               {
                   iterator.remove();

                   if (activityWeakRef != null) {
                       activityWeakRef.finish();
                   }
               }
            }
        }
    }
}

If you are planning to target older versions of android, then fragments may not be the best option what others are prescribing. Because Android 3.0, or Honeycomb, came with fundamental user interface changes, most notably in the form of the Fragment API.

In case, if you just want to remove activities from history stack and finish the activity while passing intent to another activity is your need, then

You can implement this from your AndroidManifest.xml file, just by adding android:noHistory="true" attribute in those you want

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top