Android popBackStack导致一次又一次地调用片段的CreateView

Android popBackStack导致一次又一次地调用片段的CreateView,android,android-fragments,fragment,back-stack,fragmentmanager,Android,Android Fragments,Fragment,Back Stack,Fragmentmanager,我有3个片段A、B、C。我写了一段代码来替换它们并维护backbackback: public void addFragment(Fragment fragmentToAdd, String fragmentTag) { FragmentManager supportFragmentManager = getSupportFragmentManager(); Fragment activeFragment = getActiveFragment();

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

 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,我将使用最新片段作为pop。现在由于这个原因,当长度大于1时,它会一次又一次地调用onCreate视图。 比如:

  • 打开A
  • 打开B
  • 打开C.(在打开C的情况下,调用A的创建视图。)

  • 为什么我会有这样的行为?当我删除斜体代码时,它不会发生。

    正如文档所说,行为是正常的,来自backstack事务。backback从不保存片段,它只保存事务

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

    1) 在活动中检查后台堆栈中是否有任何事务, 并在片段中添加一个标志,在您的示例中是

           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方法,您应该正确地处理它

    我通过继承(1)来自自定义BaseFragment(2)的所有片段解决了这个问题。 在这个BaseFragment中,我创建了一个变量:public static boolean removing;(3) 并在调用popbackbackimmediate()之前将其设置为true(4),然后将其重置为false。(5) 在BaseFragment child中,我检查变量。(六)

    示例代码

    活动课

        BaseFragment.removing = true; //(4)
        //pop all fragments
        while(getSupportFragmentManager().getBackStackEntryCount() > 0){
            fragmentManager.popBackStackImmediate();
        }
        BaseFragment.removing = false; //(5)
    
    碱基片段(2)

    片段子

    public class fragment extends BaseFragment{ //(1)
      @Override
      public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
          if(!removing){ // (6)
              //your code
          }
      }
    }
    

    记住
    片段的生命周期。当我们回到这里时,它将始终从
    oncreateView()开始。但我们仍然可以保存数据,然后在oncreated中处理这些数据以填充视图。对于您,您可以这样做:

    Main-activity.java

    }

    Fragment1.java

    }

    Fragment2.java

    }

    所以。。。对于
    片段
    之间的通信,我们需要您的容器
    活动
    ,通过接口。正如我们所看到的,Fragment2有一个
    接口
    ,它实现了它的
    活动
    ,当它被执行时,它调用一个方法,我们在
    fragment1
    中更改计数值,该计数值存储在
    onSaveInstanceState
    中,因此,即使再次执行
    oncreateview
    ,我们也可以继续进行任何修改。这可以用于许多其他数据,如
    arraylist、string、float、long、object、


    对不起我的“英语”

    你能详细说明一下你想用这些代码实现什么吗?@Szymon我想在抽屉里的片段之间切换,并保持后堆栈长度为1。你找到解决这个问题的方法了吗?
    public class fragment extends BaseFragment{ //(1)
      @Override
      public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
          if(!removing){ // (6)
              //your code
          }
      }
    }
    
    public class MainActivity extends AppCompatActivity implements Fragment2.myListener {
    private static final String TAG = "MainActivity";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e(TAG, "onCreate: ");
        setContentView(R.layout.activity_main);
    
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Fragment1 fragment1 = Fragment1.newInstance();
                FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
                fragmentTransaction.replace(R.id.fragmentContainer, fragment1, Fragment1.TAG);
                fragmentTransaction.addToBackStack(Fragment1.TAG);
                fragmentTransaction.commit();
            }
        });
    
    }
    
    @Override
    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
        super.onSaveInstanceState(outState, outPersistentState);
        Log.e(TAG, "onSaveInstanceState");
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.e(TAG, "onDestroy");
    }
    
    @Override
    public void bindCount(int newCount) {
        ((Fragment1)getSupportFragmentManager().findFragmentByTag(Fragment1.TAG)).setCount(newCount);
    }
    
    public class Fragment1 extends Fragment {
    public static final String TAG = "fragment1";
    private static final String SAVE_COUNT = "save_count";
    
    private int count;
    
    public Fragment1() {
    }
    
    public static Fragment1 newInstance() {
        Fragment1 fragment = new Fragment1();
        return fragment;
    }
    
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e(TAG, "onCreate: ");
        if (savedInstanceState != null) {
            count = savedInstanceState.getInt(SAVE_COUNT);
        }
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
    
        View view =  inflater.inflate(R.layout.fragment_fragment1, container, false);
    
    
        Button goToButton = (Button) view.findViewById(R.id.button);
        goToButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Fragment2 fragment2 = Fragment2.newInstance();
                FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();
                fragmentTransaction.replace(R.id.fragmentContainer, fragment2, Fragment2.TAG);
                fragmentTransaction.addToBackStack(Fragment2.TAG);
                fragmentTransaction.commit();
            }
        });
    
        return view;
    }
    
    public  void setCount(int newCount){
        count = newCount;
    }
    
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.e(TAG, "onSaveInstanceState: ");
        outState.putInt(SAVE_COUNT, count);
    }
    
    public class Fragment2 extends Fragment {
    public static final String TAG = "fragment2";
    
    public Fragment2() {
        // Required empty public constructor
    }
    
    public static Fragment2 newInstance() {
        Fragment2 fragment = new Fragment2();
    
        return fragment;
    }
    
    myListener listener;
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
    
        View view = inflater.inflate(R.layout.fragment_fragment2, container, false);
        //Here I am just modifying a value that wants to send to fragment1
        listener.bindCount(45);//newCount
    
        return view;
    }
    
    public interface myListener{
        void bindCount(int newCount);
    }
    
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        //initialice listener
        listener = (myListener) getActivity();
    }