Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change fragments without re-creation

I'm studying MVP.

I have and activity with nav menu and I change fragments from menu like this:

switch (id) {
    case R.id.nav_status:
        fragmentManager.beginTransaction().replace(R.id.fr_main, mAppProductFragment).commit();
        Log.d(TAG, "Выбрано меню статус");
        break;           
    case R.id.nav_schemas:
        AppRedirectFragment schemasFragment = new AppRedirectFragment();
        fragmentManager.beginTransaction().replace(R.id.fr_main, schemasFragment).commit();
        Log.d(TAG, "Выбрано меню переадресация");
        break;
}

The problem is that when I change the fragment, my previous fragment is destroyed. It calls the following callbacks:

D/AppProductPresenter: onStopDetouchView()
D/AppProductFragment:  onDestroyView
D/AppProductFragment: onDestroy()

It loses its reference to the presenter and also dsipose all retrofit requests. mPresenter.onDestroyView();, so all my network operations are destroyd. But Id like to run them in backgroud. But its disposed.

public void onDestroy() {
        super.onDestroy();
        mPresenter.onDestroyView();
    }

So how can change fragments without calling onDestroy being called? I read that I have to use add instead of fragmentManager.beginTransaction().replace So how do it correctly?

like image 905
Masquitos Avatar asked Jan 16 '26 19:01

Masquitos


2 Answers

When you use

fragmentManager
.beginTransaction()
.replace(R.id.fr_main, schemasFragment)
//addToBackstack(String name) //if you want to keep transaction to backstack
.commit();

replace() will remove previous fragment and add new one, so you cant avoid onDestroy(). But when you call

fragmentManager
.beginTransaction()
.add(R.id.fr_main, schemasFragment)
//addToBackstack(String name) //if you want to keep transaction to backstack
.commit();

you just add new fragment over previous one and previous fragment will still exist. But if you will add a lot of fragments without removing previous - your app can become sluggish. If your retrofit requests are complex - good decision is to do it in services.

like image 189
H.Taras Avatar answered Jan 19 '26 15:01

H.Taras


I solve a problem. The answer is use combo of: .add .attach and .detach methods. I create a function that replace a fragmetns like this:

 switch (id) {
            case R.id.nav_product:
                replaceFragment(PRODUCT_FRAGMENT);
                break;
            case R.id.nav_redirection:
                replaceFragment(REDIRECTION_FRAGMENT);
                break;
}

private void replaceFragment(String tag) {
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    Fragment currentFragment = fragmentManager.findFragmentById(R.id.fr_container);
    Fragment nextFragment = fragmentManager.findFragmentByTag(tag);

    Log.d(TAG, "f detached: " + currentFragment.toString());
    transaction.detach(currentFragment);

    if (nextFragment == null) {
        nextFragment = createFragment(tag);
        transaction.add(R.id.fr_container, nextFragment, tag);
    } else {
        Log.d(TAG, "f attach: " + nextFragment.toString());
        transaction.attach(nextFragment);
    }
    transaction.commit();
}

private Fragment createFragment(String tag) {
    Fragment result = null;
    switch (tag) {
        case CALLHISTORY_FRAGMENT:
            result = new AppCallHistoryFragment();
            break;
        case CALLTRACKING_FRAGMENT:
            result = new AppCallTrackingFragment();
            break;
        case REDIRECTION_FRAGMENT:
            result = new AppRedirectFragment();
            break;
    }
    Log.d(TAG, "create: " + result.toString());
    return result;
}

Now its ok. Fragments are Destroyed only when Activity is destroying.

like image 39
Masquitos Avatar answered Jan 19 '26 15:01

Masquitos



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!