android 控件 fragment 切换优化 混乱

来源:互联网 发布:linux编译工具链 编辑:程序博客网 时间:2024/04/26 11:55

在项目中需要进行Fragment的切换,一直都是用replace()方法来替换Fragment:然后总感觉切换的时候有些卡顿,原来的代码

  /**   * 切换页面,这里采用回调   *    */  public void switchFragment(Fragment f) {    if (f == null)      return;    FragmentTransaction transaction = getSupportFragmentManager()        .beginTransaction();    transaction.replace(R.id.fl_main, f);    // transaction.addToBackStack(descString);    transaction.commit();    // 让menu回去    menu.toggle();  }

但是,这样会有一个问题:

每次切换的时候,Fragment都会重新实例化,重新加载一边数据,这样非常消耗性能和用户的数据流量。

就想,如何让多个Fragment彼此切换时不重新实例化?

翻看了Android官方Doc,和一些组件的源代码,发现,replace()这个方法只是在上一个Fragment不再需要时采用的简便方法。

正确的切换方式是add(),切换时hide(),add()另一个Fragment;再次切换时,只需hide()当前,show()另一个。

这样就能做到多个Fragment切换不重新实例化

  /**   * 切换页面的重载,优化了fragment的切换   *    * @param f   * @param descString   */  public void switchFragment(Fragment from, Fragment to) {    if (from == null || to == null)      return;    FragmentTransaction transaction = getSupportFragmentManager()        .beginTransaction().setCustomAnimations(R.anim.tran_pre_in,            R.anim.tran_pre_out);    if (!to.isAdded()) {        // 隐藏当前的fragment,add下一个到Activity中        transaction.hide(from).add(R.id.fl_main, to).commit();      } else {        // 隐藏当前的fragment,显示下一个        transaction.hide(from).show(to).commit();      }    // 让menu回去    menu.toggle();  }
实用代码

private void setTabSelection(int index) {//获得事务FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();hideFragment(fragmentTransaction);//把所有的fragment都隐藏changeNormal();//把导航栏全部设置为 未选switch (index) {case 0:imgBtn[0].setImageResource(imgChecked[0]);txtBtn[0].setTextColor(getResources().getColor(R.color.top_color));//设置为被选(文字,图片)HomeFragment hotSellFragment = (HomeFragment) fragmentManager.findFragmentByTag("one");if (hotSellFragment == null) {fragmentTransaction.add(container, new HomeFragment(), "one");//要么添加一个在栈的最上面} else {fragmentTransaction.show(hotSellFragment);//要么就把隐藏的show显示出来}break;..........................}}//用来隐藏fragmentprivate void hideFragment(FragmentTransaction fragmentTransaction) {HomeFragment hotSellFragment = (HomeFragment) fragmentManager.findFragmentByTag("one");if (hotSellFragment != null) {fragmentTransaction.hide(hotSellFragment);}}//把导航栏的文字和图片都设置为 "灰"private void changeNormal() {for (int i = 0; i < imgBtn.length; i++) {imgBtn[i].setImageResource(imgsNormal[i]);txtBtn[i].setTextColor(getResources().getColor(R.color.gray));}}


混乱
有时候我们推出程序进行操作,或者程序报错的时候,有很大几率会出现fragment重叠的现象。 通过搜集相关资料,我找到了原因,在我切换到其他app的时候,fragment所在activity已经被销毁(这一句话是不是让你恍然大悟,我是这么认为的)。并且通过onSaveInstanceState这个方法保存了相关的数据。
  当我再次回到这个app的时候,通过onCreate中的参数savedInstanceState恢复了之前的fragment。此时的FragmentTransaction中的相当于又再次add了fragment进去的,之前保存的fragment也还在。hide()和show()方法对之前保存的fragment已经失效了。所以出现了重叠的现象。 解决方法如下,在进入onCreate函数时,先去判断savedInstanceState是否为null,如果不为null,则表示里面有保存这四个fragment。则不再重新去add这四个fragment,而是通过Tag从前保存的数据中直接去读取。相关代码如下:
public void onCreate(Bundle savedInstanceState) {  
    fManager = getFragmentManager();  
    if (savedInstanceState != null) {  
        allFrg = (AllOfficialAccountFragment) fManager.findFragmentByTag("allFrg");  
        movieFrg = (MovieOfficialAccountFragment) fManager.findFragmentByTag("movieFrg");  
        newsFrg = (NewsOfficialAccountFragment) fManager.findFragmentByTag("newsFrg");  
        otherFrg = (OtherOfficialAccountFragment) fManager.findFragmentByTag("otherFrg");           
    }  
    super.onCreate(savedInstanceState);       
}
另外一个思路是,直接在包含Fragment的Activity中复写
public void onSaveInstanceState(Bundle outState) {  
    // TODO Auto-generated method stub       
    //Log.v("LH", "onSaveInstanceState"+outState);  
    //super.onSaveInstanceState(outState);   //将这一行注释掉,阻止activity保存fragment的状态
}
0 0
原创粉丝点击