Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android onDetach() not called when I replace fragment

I have two fragments (FRAGMENT_1, FRAGMENT_2). FRAGMENT_1 is running a timer and when I open FRAGMENT_2, I want FRAGMENT_1 to keep running it.

FRAGMENT_1 in onCreate():

if (savedInstanceState == null) {
    FRAGMENT_1 fragment1= new FRAGMENT_1();
    fragment1.setRetainInstance(true);
    getSupportFragmentManager()
        .beginTransaction()
        .add(R.id.main_fragment_container, fragment1, FRAGMENT_1_TAG)
        .addToBackStack(null)
        .commit();
}

This is my navigation between fragments:

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    int id = item.getItemId();
    Fragment fragment = null;
    String fragTag = "";
    switch (id) {
        case R.id.nav_frag_1:
            //this method returns
            //getSupportFragmentManager().getFragments()
            //.contains(getSupportFragmentManager().findFragmentByTag(tag))
            if (isFragmentCreated(FRAGMENT_1_TAG)) {
                fragment = getSupportFragmentManager()
                        .findFragmentByTag(FRAGMENT_1_TAG);
            } else {
                fragment = new FRAGMENT_1();
            }
            fragTag = FRAGMENT_1_TAG;
            break;

        case R.id.nav_frag_2:
            fragment = new FRAGMENT_2();
            fragTag = FRAGMENT_2_TAG;
            break;

        case R.id.nav_settings:
            Intent intent = new Intent(this, SettingsActivity.class);
            startActivity(intent);
            break;

    }
    if (fragment != null && !fragment.isVisible()) {
        FragmentTransaction fragmentTransaction = getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.main_fragment_container, fragment, fragTag);
        if (fragment.getTag().equals(FRAGMENT_1_TAG)){
            fragmentTransaction.addToBackStack(null);
        }
        fragmentTransaction.commit();
    }

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
    return true;
}

When I navigate between these fragments, FRAGMENT_2 doesn't call onDetach() therefore it is not removed, but if I remove the following piece of code:

if (fragment.getTag().equals(TIMER_FRAGMENT_TAG)){
    fragmentTransaction.addToBackStack(null);
}

then FRAGMENT_2 calls onDetach() and then gets removed. Why is this happening?

like image 606
Dainius Miežiūnas Avatar asked Jan 26 '17 10:01

Dainius Miežiūnas


People also ask

Is onDetach always called?

onDetach() is always called after any Lifecycle state changes. Note that these callbacks are unrelated to the FragmentTransaction methods attach() and detach() . For more information on these methods, see Fragment transactions.

How to replace one fragment with another in Android?

Use replace() to replace an existing fragment in a container with an instance of a new fragment class that you provide. Calling replace() is equivalent to calling remove() with a fragment in a container and adding a new fragment to that same container. transaction.

When onAttach is called?

onAttach() the first method in the fragment lifecycle. It's called when a fragment is first associated with an activity. getActivity() will return null if it is called before onAttach().

How to remove fragment from FragmentManager?

You need add/commit fragment using one tag ex. "TAG_FRAGMENT". Fragment fragment = getSupportFragmentManager(). findFragmentByTag(TAG_FRAGMENT); if(fragment !=


1 Answers

In Fragment lifecycle methods for destroying calls with this turn onPause() -> onStop() -> onDestroyView() -> onDestroy() -> onDetach().

addToBackStack(null) method adds fragment to backStack, i.e it saves fragment instance and when fragment became invisible, system calls fragment onDestroyView() method because view destroyed, but after it system doesn't call method onDestroy() because fragment instance saved in backStack and there is reference on fragment instance and it doesn't destroy. And if instance not destroyed system keeps that instance attached to activity and doesn't call onDetach() it.

like image 190
Levon Vardanyan Avatar answered Sep 22 '22 14:09

Levon Vardanyan