一、概述

在一个Activity+多个Fragment的回退处理,一开始使用传统的add加hide,show进行判断切换,这样对于同级fragment用着挺不错的,比如导航栏类似的功能,多个层级的回退就需要添加判断很不实用,所以用到了addToBackStack,popBackStack来实现。还有就是自己定义一个list来管理fragment,这个可以参考文章。

hide和show的导航栏:

private void hideAllFragment(FragmentTransaction fTransaction)

{

if (detailFragment!=null)fTransaction.hide(detailFragment);

if (listFragment!=null)fTransaction.hide(listFragment);

if (searchFragment!=null)fTransaction.hide(searchFragment);

}

public void openDetailFragment(int fragment_type){

FragmentTransaction fTransaction = fManager.beginTransaction();

//首先隐藏清单fragment

hideAllFragment(fTransaction);

//再显示详细fragment

switch (fragment_type) {

case KTVType.FragmentType.ROOMDETAIL:

if (detailFragment == null){

detailFragment=new HistoryOderdetailFragment();

fTransaction.add(R.id.setting_content, detailFragment);

}

else

fTransaction.show(detailFragment);

break;

case KTVType.FragmentType.PRODUCTDETAIL:

...

}

fTransaction.commit();

}

二、回退栈使用

具体生命的周期分析可以参考文章,重写onBackPressed  用于back回退和toolbar的回退配合使用()

private void initFragment(){

fManager = getSupportFragmentManager();

FragmentTransaction fTransaction = fManager.beginTransaction();

settingFragment = new SettingFragment();

fTransaction.add(R.id.setting_content, settingFragment);

// fTransaction.addToBackStack(null);

fTransaction.commit();

}

/**

* 打开对应的fragment

* @param fragment_type

*/

public void openFragment(int fragment_type)

{

FragmentTransaction fTransaction = fManager.beginTransaction();

switch (fragment_type) {

case KTVType.FragmentType.ROOMDETAIL:

if (roomDetailsFragment == null)

roomDetailsFragment = new RoomDetailsFragment(this);

fTransaction.replace(R.id.setting_content, roomDetailsFragment);

break;

case KTVType.FragmentType.PRODUCTDETAIL:

if (productDetailsFragment == null)

productDetailsFragment = new ProductDetailsFragment(this);

fTransaction.replace(R.id.setting_content, productDetailsFragment);

break;

case KTVType.FragmentType.ADDROOM:

if (addRoomFragment == null)

addRoomFragment = new AddRoomFragment();

fTransaction.replace(R.id.setting_content, addRoomFragment);

break;

case KTVType.FragmentType.ADDPRODUCT:

if (addProductFragment == null)

addProductFragment = new AddProductFragment(this);

fTransaction.replace(R.id.setting_content, addProductFragment);

break;

default:

}

fTransaction.addToBackStack(null);

fTransaction.commit();

}

@Override

public void onBackPressed() {

if (getSupportFragmentManager().getBackStackEntryCount() <= 0)//这里是取出我们返回栈存在Fragment的个数

finish();

else

getSupportFragmentManager().popBackStack();

}

replace,add看需求使用:我这里是需要每次都是刷新的,所以采用replace,

replace方法添加新的Fragment在回退的时候Fragment会重新加载,

add 配合 hide使用,能保存fragment状态不会每次刷新视图。

注意:add配合hide不能使用上面的hideAllFragment这样会隐藏掉所有对象,再次add不会出现,所以在每次add的同时hide上一个。

eg:代码不变,add代替replace,同时添加hide,这样布局就不会重新加载相当于hide和show。

private void initFragment(){

...

fTransaction.add(R.id.setting_content, settingFragment, 0+"");

...

}

public void openFragment(int fragment_type){

...

fTransaction.add(R.id.setting_content, roomDetailsFragment,1+"");

...

fTransaction.add(R.id.setting_content, productDetailsFragment,2+""));

...

fTransaction.addToBackStack(null);

fTransaction.hide(fManager.findFragmentByTag(0+""));

fTransaction.commit();

}

注意:当Fragment被另一个Fragment replace(), 并且压入back stack中, 此时它的View是被销毁的, 但是它本身并没有被销毁.

也即, 它走到了onDestroyView(), 却没有走onDestroy()和onDetact()。等back回来的时候, 它的view会被重建, 重新从nCreateView()开始走生命周期。在这整个过程中, 该Fragment中的成员变量是保持不变的, 只有View会被重新创建.

在这个过程中, instance state的saving并没有发生。参考文章

public class TransactionActivity extends BaseActivity {

//定义三种fragment类型

private FragmentManager fManager;//获取管理器

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_transaction);

hideStatusBar();

inirFragment();

}

private void inirFragment(){

fManager = getSupportFragmentManager();

FragmentTransaction fTransaction = fManager.beginTransaction();

fTransaction.add(R.id.history_fragment_content, new HistoryOrderlistFragment());

//fTransaction.addToBackStack(null);//会出现空白页

fTransaction.commit();

}

/**

* 打开对应的fragment

*/

public void openFragment(@Nullable KTVOrderInfo orderInfo)

{

BaseFragment baseFragment = null;

FragmentTransaction fTransaction = fManager.beginTransaction();

if (orderInfo!=null)

fTransaction.replace(R.id.history_fragment_content, new HistoryOderdetailFragment(orderInfo));

else

fTransaction.replace(R.id.history_fragment_content, new SearchFragment());

fTransaction.addToBackStack(null);

fTransaction.commit();

}

@Override

public void basefinish() {

if (getSupportFragmentManager().getBackStackEntryCount() <= 0)//这里是取出我们返回栈存在Fragment的个数

finish();

else

getSupportFragmentManager().popBackStack();

}

}

Notes:这种初始化的fragment使用add/replace,不要添加到addToBackStack里面,不然最后一下回退会出现空白页。

三、回退栈修改版

由于回退栈虽然销毁了视图但是实例还在,数据还在,再次加载的时候回到原来的状态,对于这次的项目不太适合,所以采用参考list控制的方式来控制。

//因为是replace是所以添加fragment的类型,如果hide,show可以使用Listprivate ListfragmentTypeList = new ArrayList<>();

/**

* 打开对应的fragment

* @param fragment_type

* @param isBack 是否是后退操作,用于判定动画方向

*/

public void openFragment(int fragment_type,boolean isBack)

{

BaseFragment baseFragment = null;

FragmentTransaction fTransaction = fManager.beginTransaction();

if (isBack)

fTransaction.setCustomAnimations(R.anim.slide_left_in,R.anim.slide_right_out);

else

fTransaction.setCustomAnimations(R.anim.slide_right_in,R.anim.slide_left_out);

switch (fragment_type) {

case KTVType.FragmentType.ROOMDETAIL:

baseFragment = new RoomDetailsFragment(this);

break;

case KTVType.FragmentType.PRODUCTDETAIL:

baseFragment = new ProductDetailsFragment(this);

break;

case KTVType.FragmentType.ADDROOM:

baseFragment = new AddRoomFragment();

isEditContent = true;

break;

case KTVType.FragmentType.ADDPRODUCT:

baseFragment = new AddProductFragment(this);

isEditContent = true;

break;

case KTVType.FragmentType.SETTING:

baseFragment = new SettingFragment();

break;

default:

}

fragmentTypeList.add(fragment_type);

fTransaction.replace(R.id.setting_content, baseFragment);

fTransaction.commit();

}

@Override

public void basefinish() {

if (fragmentTypeList.size() > 1) {

int temp = fragmentTypeList.get(fragmentTypeList.size()-2);

//连续去除集合后两位

fragmentTypeList.remove(fragmentTypeList.size()-1);

fragmentTypeList.remove(fragmentTypeList.size()-1);

openFragment(temp,true);

}else

finish();

}

更多推荐