Home » Android » android – How to go back to a specific activity if activities are implemented by same class

android – How to go back to a specific activity if activities are implemented by same class

Posted by: admin June 16, 2020 Leave a comment

Questions:

To implement the up navigation, I would like to go back to a specific activity on the history stack. If the activities on the stack are implemented by different classes, it works like this (assuming I have activities A, B and C on the stack and want to go back to activity A:

protected void onUpPressed() {
    Intent intent = new Intent(this, A.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
                  | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    startActivity(intent);
    finish();
}

Android will pop activities off the stack until the activity specified by the intent is the top most (activity implemented by class A in this case).

However, my app has several activities on the stack implemented by the same class. That’s because they display the same kind of data but for different objects. They were launched with an intent that specified both the class implementing the activity and the object to display (either in the extras bundle or in the data property).

Now I’m looking for code to again pop several activities off the history stack until the matching activity the top most. If I extend the above code and additionally set the extras bundle or the data property, it doesn’t work. Android always matches the first activity implemented by the specified class and doesn’t go back far enough. The extras bundle and the data property are ignored.

protected void onUpPressed() {
    Intent intent = new Intent(this, A.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
                  | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    intent.setData(Uri.parse("myapp:" + rootId));
    startActivity(intent);
    finish();
}

So how can I achieve to go back to a specific activity? What intent fields does Android compare to determine if it has found the desired activity?

How to&Answers:

To implement FLAG_ACTIVITY_CLEAR_TOP, Android searches through your task’s activity stack (from top to bottom) using the following test:

                if (r.realActivity.equals(newR.realActivity)) {

Your problem is that realActivity is a ComponentName (so the above comparison locates the topmost activity in the stack that matches on package and class name): no further test is performed against the intent, so it is impossible to be any more specific about which of that component’s activities you wish to target.

Therefore:

  1. So how can I achieve to go back to a specific activity?

    There is no native means of accomplishing this. Your best bet is probably to manually implement a form of bubbling as suggested by @VM4.

  2. What intent fields does Android compare to determine if it has found the desired activity?

    Only the component name.

Answer:

As you described, you have one Activity that show different content based on the starting Intent. Well, why not Fragments?

I don’t know the details of your applications architecture, but is should be easy to refactor that Activity to a Fragment. There could be a FragmentActivity that wraps all the Fragments which responsible for showing the content. This way you would have much more freedome to handle the activity’s stack of fragments.

Steps summarized:

  • Convert your existing Activity (that show the content) to a Fragment.
  • Make a FragmentActivity (that will manage the Fragments).
  • Make the FragmentActivity “singleInstance”, so it will cache all the
    “startActivity” requests, where you have the opportunity to add a
    new Fragment representing the new content to show.

You could add fragments this way:

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);

    // ContentFragment is the Fragment that you made from your Activity.
    // Here you can pass the intent that stores the object to show also,
    // so the parsing of the intent would be the same.
    ContentFragment fragment = ContentFragment.newInstance(intent);

    getFragmentManager()
    .beginTransaction()
    .add(fragment, null)
    .addToBackStack("id here that will be used at pop")
    .commit();
}

And you can pop to a specific id this way:

getFragmentManager().popBackStack(“id here”, 0);

This solution has a side-effect. The fragments will stick together, so you cannot insert any other Activity between them. This is trivial, but worth mentioning since differs from your current implementation.

I also assumed that you are familiar with how “singleInstance” and Fragments work. Fell free to ask if something is not clear.

Answer:

I recommend storing your data model outside of the extras, using a singleton to access, and refreshing an activity using that data model on the onResume()

Answer:

Lets say you are in /home/usr/vm4/development and in this activity you have somekind of Views (lets say TextViews) that let you go to all parent directories. (Clicking on for example “usr” will go to /home/usr. In windows it looks like this:

enter image description here

I don’t think Android lets you back into a specific Activity based on extra data. However you can do a trick here. The View (that when clicked takes you somewhere) can have a String tag attached to it:

TextView link = new TextView();
link.setTag("/home/usr");

Now when you click this View in the onClick() method:

onClick(View v) { 
   String extra = v.getTag(); 
   // start your activity with extras here.
}

Now you just need to make sure you add the right tags to your links when inflating the activity.