popBackStack导致反复调用片段的oncreateView[英] popBackStack causes calling oncreateView of fragment again and again

本文是小编为大家收集整理的关于popBackStack导致反复调用片段的oncreateView的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我有 3 个片段 A、B、C.我写了一段代码来替换它们并维护 backstack:

 public void addFragment(Fragment fragmentToAdd, String fragmentTag) {
        FragmentManager supportFragmentManager = getSupportFragmentManager();
        Fragment activeFragment = getActiveFragment();
        FragmentTransaction fragmentTransaction = supportFragmentManager
                .beginTransaction();
        if (null != activeFragment) {
            fragmentTransaction.hide(activeFragment);
        }
        fragmentTransaction.replace(R.id.layout_child_activity, fragmentToAdd,
                fragmentTag);

       if (supportFragmentManager.getBackStackEntryCount() > 1) {
            supportFragmentManager.popBackStack();
        }
        fragmentTransaction.addToBackStack(fragmentTag);
        fragmentTransaction.commit();
    }

在这段代码中

if (supportFragmentManager.getBackStackEntryCount() > 1) {
    supportFragmentManager.popBackStack();
}

如果堆栈长度大于 1,我会使用弹出最新的片段.现在由于这个原因,当长度大于 1 时,它会一次又一次地调用 onCreate 视图.喜欢:

  1. 打开 A.
  2. 打开 B.
  3. 打开C.(如果打开C.调用A的onCreateView.)

为什么我会出现这种行为?当我删除该斜体代码时,它不会发生.

推荐答案

正如文档所说,行为是正常的,来自后台事务.backstack 从不保存 Fragments,它只是保存事务

在此处输入图片描述

http://developer.android.com/intl/es/guide/components/fragments.html

我所做的,我不确定是否是最好的方法,但是当我想清除所有交易时,我会这样做

1) 在您的 Activity 中检查后台堆栈中是否有任何交易,并在您的片段中添加一个标志,在您的情况下是 A

       int backStackCount = getSupportFragmentManager().getBackStackEntryCount();

       if(backStackCount > 0) {
           Transactions.MUST_DETACH_FROM_BACKSTACK = true;
           getSupportFragmentManager().popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
       }

2) 在片段 A 中,获取标志并删除片段 onCreateView 并像这样返回 null

public class Transactions extends android.support.v4.app.Fragment{

public static boolean MUST_DETACH_FROM_BACKSTACK = false;

public Transactions() {
    // Required empty public constructor
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    Log.i("FRAGMENT", "onCreateView "+MUST_DETACH_FROM_BACKSTACK);
    // Inflate the layout for this fragment
    if (MUST_DETACH_FROM_BACKSTACK) {
        MUST_DETACH_FROM_BACKSTACK = false;
        getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
        return null;
    }
    return inflater.inflate(R.layout.fragment_transactions, container, false);
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);


    Log.i("FRAGMENT", "onViewCreated");
    if(view != null){

        Log.i("FRAGMENT", "ThreadStarted");
        startThread(view);
    }
}

但要小心,我在 onResume() 之后调用了

OnCreateView()

即使使用 getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();

所以如果你有任何 conde onResume 方法你应该正确处理它

本文地址:https://www.itbaoku.cn/post/2091038.html

问题描述

I have 3 fragment A, B,C.I wrote piece of code for replacing them and maintaining backstack:

 public void addFragment(Fragment fragmentToAdd, String fragmentTag) {
        FragmentManager supportFragmentManager = getSupportFragmentManager();
        Fragment activeFragment = getActiveFragment();
        FragmentTransaction fragmentTransaction = supportFragmentManager
                .beginTransaction();
        if (null != activeFragment) {
            fragmentTransaction.hide(activeFragment);
        }
        fragmentTransaction.replace(R.id.layout_child_activity, fragmentToAdd,
                fragmentTag);

       if (supportFragmentManager.getBackStackEntryCount() > 1) {
            supportFragmentManager.popBackStack();
        }
        fragmentTransaction.addToBackStack(fragmentTag);
        fragmentTransaction.commit();
    }

Here in this piece of code

if (supportFragmentManager.getBackStackEntryCount() > 1) {
    supportFragmentManager.popBackStack();
}

I using for pop the latest fragment if stack length is more than 1. Now due to this when length is going greater than 1 than it is calling onCreate view again and again. Like :

  1. open A.
  2. open B.
  3. open C.(In case of open C. onCreateView of A is called. )

Why I am getting such kind of behavior ? When I am removing that italic code than it is not happening.

推荐答案

Than behavior is normal, coming from the backstack transaction, as the docs say. The backstack never saves Fragments, it just saves the transaction

enter image description here

http://developer.android.com/intl/es/guide/components/fragments.html

What I do, I am not sure if, is it the best way but when I want to clear all the transactions I do this

1) INSIDE YOUR ACTIVITY check if is there any transactions in the back stack, and add a flag inside your fragment, in your case is A

       int backStackCount = getSupportFragmentManager().getBackStackEntryCount();

       if(backStackCount > 0) {
           Transactions.MUST_DETACH_FROM_BACKSTACK = true;
           getSupportFragmentManager().popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
       }

2) Inside your fragment A, get the flag and Remove the fragment onCreateView and return null like this

public class Transactions extends android.support.v4.app.Fragment{

public static boolean MUST_DETACH_FROM_BACKSTACK = false;

public Transactions() {
    // Required empty public constructor
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    Log.i("FRAGMENT", "onCreateView "+MUST_DETACH_FROM_BACKSTACK);
    // Inflate the layout for this fragment
    if (MUST_DETACH_FROM_BACKSTACK) {
        MUST_DETACH_FROM_BACKSTACK = false;
        getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
        return null;
    }
    return inflater.inflate(R.layout.fragment_transactions, container, false);
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);


    Log.i("FRAGMENT", "onViewCreated");
    if(view != null){

        Log.i("FRAGMENT", "ThreadStarted");
        startThread(view);
    }
}

BUT BE CAREFULL I Get onResume() Called after the

OnCreateView()

even with getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();

So if you have any conde onResume method you should handle it properly