2

I have two Activities: MainActivity and OtherActivity. A fragment in MainActivity launches the OtherActivity, but when I press the back button at the top, it returns me to the MainActivity instead of the fragment that launched the OtherActivity.

The end result is the enduser is sent back to the main screen instead of the fragment that they were using.

This is my manifest. I have set MainActivity to be the parent of OtherActivity:

    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name=".OtherActivity"
        android:parentActivityName="com.example.test.MainActivity" >
    </activity>

In MainActivity, when a user clicks on a button, it loads a List fragment:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // ...

    button.findViewById(R.id.events).setOnClickListener(new View.OnClickListener() {

         Fragment ef = new MyItemsFragment();
         FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
         fragmentTransaction.addToBackStack(null);
         fragmentTransaction.replace(R.id.content, ef, "my_fragment");
         fragmentTransaction.commit();
     });

}

public void callOtherActivity() {
    Intent i = new Intent(this, OtherActivity.class);
    this.startActivity(i);
}

When an item is clicked in the List Fragment, it launches OtherActivity. A lot of the code for this was auto-generated by android studio. I have changed some of it. In MyItemsRecyclerViewAdapter:

@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
    holder.mItem = mValues.get(position);

    holder.mView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (null != mListener) {
                // Notify the active callbacks interface (the activity, if the
                // fragment is attached to one) that an item has been selected.
                mListener.onEventFragmentInteraction(holder.mItem);

                MainActivity ma = (MainActivity) holder.mView.getContext();
                ma.callOtherActivity();

            }
        }
    });
}

Notice it calls ma.callOtherActivity(), which is defined in MainActivity and will launch OtherActivity when an item is clicked in the list fragment.

This is OtherActivity:

public class OtherActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_other);
    }

}

Now, when I click on the back arrow button in OtherActivity, the app will just show MainActivity, and not the List fragment that the user last saw.

How can I make sure that on return from OtherActivity, the user will see the list fragment again for better user experience?

EDIT: There seems to be confusion about the 'back' button. Maybe they are the same, but I am talking about the one when switching Activities. It is not the back button used to exit the application. See image

doejoe
  • 125
  • 2
  • 8
  • try to remove addToBackStack(null) while calling fragment and see – Mohit Suthar Jul 18 '17 at 05:53
  • Remove android:parentActivityName="com.example.test.MainActivity" from manifest file and try .Whenever you click on the back button , it basically launches the MainActivity as fresh activity.Please let me know if im wrong. – SriMaharshi Manchem Jul 18 '17 at 06:25
  • There is only one "Back" button and it is usually used to navigate the back stack. I think your update is saying that you are referring to the "Up" button. https://developer.android.com/training/appbar/up-action.html – Kuffs Jul 18 '17 at 06:34

5 Answers5

1

When you start a new activity, the existing one is stacked so you can retrieve it later such as when you press the Back key.

On pressing the Back key, the Activity is restarted. This is the important part. It is not just brought back exactly as it was when it was last used. This means that you as the developer must take care to restore the Activity back to the state that you want it to be in. Any fragments will already be in the correct state but you must take care to not overwrite that state when your Activity restarts.

In your case, I suspect that your MainActivity code is indiscriminately re-initialising your fragments instead of checking whether fragments already exist for that particular activity before conditionally initialising them only if they don't.

It is difficult to say for sure as you do not include any of that code in your question. Check the code that displays the fragments in your MainActivity. Before you display them, are you checking whether there are already fragments visible? If not, you should be.

For example, the code below in an Activity, first checks whether a fragment is already displayed before it adds a new one. Essentially, the first time this is run, there will be no Fragments and therefore existing will be null and a new Fragment will be created and displayed.

After you have started a new OtherActivity etc and then returned to this activity with the Back key, existing will no longer be null as the Fragment system will have restored any existing fragments back into your container. Therefore we actually just do nothing.

@Override
protected void onCreate(Bundle b) {
    super.onCreate(b);

    Fragment existing = getSupportFragmentManager().findFragmentById(R.id.content);

    if (existing == null) {
        Fragment newFragment = new MyFragment();
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.content, newFragment)
                .commit();
    }

}

Hope this is clear.

Kuffs
  • 35,581
  • 10
  • 79
  • 92
  • 1
    That fragment already has data loaded, so I had `fragmentTransaction.addToBackStack(null);`. Can I not restore this from the backstack when the main activity restarts after returning from the other activity? – doejoe Jul 18 '17 at 13:29
  • `R.id.content` is actually the main activity's content. Should that be the fragment, so `.findFragmentByTag("my_fragment")` since I created a tag for it in the transaction after the button click? But if it exists, how do I load it with its existing data? Your sample recreates the fragment from scratch if nothing exists. – doejoe Jul 18 '17 at 13:32
  • My advice (and code sample) is rather general as you did not include any of your fragment creation code. It may be relevant, it may not but it is a common error that I have seen people make and your description of your problem made it sound like this was a possible cause. – Kuffs Jul 19 '17 at 07:26
0

Just delete this line fragmentTransaction.addToBackStack(null);

azisuazusa
  • 317
  • 1
  • 12
0

you can use getSupportFragmentManager().getBackStackEntryCount(); method in MainActivity's onBackPressed Method. OnClick bottom System back button. follow below method.

@Override
public void onBackPressed() {    
int backstack = getSupportFragmentManager().getBackStackEntryCount();
 if (backstack > 0) {
        getSupportFragmentManager().popBackStack();
    } else {
            super.onBackPressed();
            System.exit(0);
      }}

In fragment, press the back button at the top. try this, in onCreate method or onCreateView method of Fragment call this default method

setHasOptionsMenu(true);

and then override below method:

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
             getFragmentManager().popBackStack();
             break;
         }
       return super.onOptionsItemSelected(item);
}
Dhiren Basra
  • 820
  • 9
  • 24
0

You can use Activity for result for this start Other Activity and as soon as you want to finish OtherActivity just do setResult, MainActivity would receive this result and there do the following

if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
        getSupportFragmentManager().popBackStack();
    }

The code would go like this in MainActivity

public void callOtherActivity() {
    Intent i = new Intent(this, OtherActivity.class);
   startActivityForResult(i, 1);
}

and in OtherActivity's onBackPress call below method.

Intent returnIntent = new Intent();
returnIntent.putExtra("result",result);
setResult(Activity.RESULT_OK,returnIntent);
finish();

and now in MainActivity onActivityresult

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == 1) {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
            getSupportFragmentManager().popBackStack();
        }
    }
 }
Ankit Khare
  • 1,345
  • 11
  • 30
0

I might be late but in my case error was coming because of the LoadFragment Method in OnStart method of MainActivity

Vikash Sharma
  • 539
  • 8
  • 13