popBackStack导致一次又一次调用片段的oncreateView
Posted
技术标签:
【中文标题】popBackStack导致一次又一次调用片段的oncreateView【英文标题】:popBackStack causes calling oncreateView of fragment again and again 【发布时间】:2014-04-12 06:47:58 【问题描述】:我有 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 视图。 喜欢:
-
打开 A.
打开 B.
打开C.(如果打开C.调用A的onCreateView。)
为什么我会出现这种行为?当我删除该斜体代码时,它不会发生。
【问题讨论】:
您能否详细说明您想通过使用该代码实现什么? @Szymon 我想在抽屉中的片段之间切换并保持回栈长度为 1。 你找到解决这个问题的办法了吗? 【参考方案1】:正如文档所说,来自后台事务的行为是正常的。 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 方法你应该正确处理它
【讨论】:
【参考方案2】:我通过从我的自定义 BaseFragment (2) 继承 (1) 所有片段解决了这个问题。 在这个 BaseFragment 中,我创建了一个变量: public static boolean removal; (3) 并在调用 popBackStackImmediate() 之前将其设置为 true (4),然后将其重置为 false。 (5) 在 BaseFragment-childs 我检查变量。 (6)
示例代码
活动类
BaseFragment.removing = true; //(4)
//pop all fragments
while(getSupportFragmentManager().getBackStackEntryCount() > 0)
fragmentManager.popBackStackImmediate();
BaseFragment.removing = false; //(5)
BaseFragment (2)
public class BaseFragment extends Fragment
public static boolean removing = false; //(3)
片段-孩子
public class fragment extends BaseFragment //(1)
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState)
if(!removing) // (6)
//your code
【讨论】:
【参考方案3】:记住fragment
的生命周期。当我们回到这一点时,它将始终从oncreateView()
开始。但是我们仍然可以保存数据,然后我们将在 oncreated 中处理这些数据以填充我们的视图。你可以这样做:
Main-activity.java
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);
Fragment1.java
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);
Fragment2.java
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();
所以...对于fragments
之间的通信,我们将需要您的容器activity
,通过接口。正如我们所见,Fragment2 有一个interface
,它实现了它的activity
,当它执行时,它调用了一个方法,我们改变fragment1
中的计数值,它存储在onSaveInstanceState
中,所以我们可以恢复即使再次执行oncreateview
,也会发生任何修改。这可以用于许多其他数据,例如arraylist, string, float, long, object,
等。
对不起我的“英语”!!!!!!
【讨论】:
以上是关于popBackStack导致一次又一次调用片段的oncreateView的主要内容,如果未能解决你的问题,请参考以下文章