改善侧滑菜单Fragment切换速度(解决Fragment切换加载慢的问题)

1.现状:

在做项目的时候很多时候需要使用侧滑菜单。侧滑菜单项一般都是用Fragment。

一般设计上是在Home page的layout中使用FrameLayout 作为一个container 如:content_main.xml




    

    


用户将FrameLayout 作为Fragment的容器。 在app开始运行的时候,Home的Fragment先填充这个FrameLayout。

当用户切换的时候,用下面语句去替换原有的Fragment。


fragmentManager.beginTransaction().replace(R.id.container, new HomeFragment()).commit();
2.存在的问题
这种设计对于Fragment简单的页面非常简单实用。 开发者不用考虑任何东西。直接替换container中的内容就可以。
但是如果每个Fragment很复杂,Fragment中的数据加载又很好时,这就会出现问题。
因为每次调用replace的时候,新的Fragment需要重新初始化,重新加载数据,屏幕会出现加载等待或白色闪屏。这样的用户体验很不好。
如下图:

例子代码:
http://pan.baidu.com/s/1mhYVdzE
(真搞不懂,CSDN 网站已经好多年了,博客功能还停留在10年前,连代码分享都不做上去。来需要求baidu。)

3.解决的方法:
在FragmentTransaction类中不仅仅提供了replace方法,同时提供了hide/show方法。
我们可以使用这个方法实现快速切换。
效果如下图:

例子代码:
http://pan.baidu.com/s/1slH0kAp

首先提供一个简单的类:

package com.xiaohui.androidhome.tabnavigationbar;


import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;

/**
 * Created by xiaohui on 6/13/16.
 */
public class FragmentSwitcher {
    /**
     *Configure your fragments.
     */
    public static final String FRAGMENT_HOME = "QQ";
    public static final String FRAGMENT_163 = "163";
    public static final String FRAGMENT_SINA = "sina";

    private final String [] fragmentTagPool = new String[]{
            FRAGMENT_HOME,
            FRAGMENT_163,
            FRAGMENT_SINA
    };

    private final Fragment[] fragmentPool = new Fragment[]{
            new HomeFragment(),
            new News163Fragment(),
            new SinaFragment()
    };

    private final int homeFragmentIndex = 0;

    /**
     * The following code that user doesn't need to modify.
     */
    public String curFragmentTag = fragmentTagPool[homeFragmentIndex];

    FragmentManager fragmentManager;

    public  FragmentSwitcher(FragmentManager mgr){
        fragmentManager = mgr;
        addFragments();
    }

    public void onSaveInstanceState (){
        /**
         * If system kills the home activity or the screen rotation happened.
         * The switcher need to be rebuilt. So we need to remove all fragment from fragment mananger.
         * Otherwise these fragments will overlap together.
         */
        removeAllFragment();
    }

    public void onStart (){
        onlyShowHomeFragment ();
    }

    public void onResume (){
        fragmentManager.beginTransaction().show(fragmentManager.findFragmentByTag(curFragmentTag)).commit();
    }

    public void showFragmentByTag(String tag){
        if (tag.equals(curFragmentTag)){
            return;
        }

        fragmentManager.beginTransaction().hide(fragmentManager.findFragmentByTag(curFragmentTag)).commit();
        curFragmentTag = tag;
        fragmentManager.beginTransaction().show(fragmentManager.findFragmentByTag(curFragmentTag)).commit();
    }

    private void addFragments (){
        for (int i = 0; i < fragmentPool.length; i ++){
            fragmentManager.beginTransaction().add(R.id.container, fragmentPool[i], fragmentTagPool[i]).commit();
        }
    }

    private void onlyShowHomeFragment (){
        for (int i = 0; i < fragmentPool.length; i ++) {
            if (homeFragmentIndex == i){
                fragmentManager.beginTransaction().show(fragmentPool[i]).commit();
            }else {
                fragmentManager.beginTransaction().hide(fragmentPool[i]).commit();
            }
        }
    }

    private void removeAllFragment(){
        for (int i = 0; i < fragmentPool.length; i ++){
            fragmentManager.beginTransaction().remove(fragmentPool[i]).commit();
        }
    }
}

这个类做为辅助切换Fragment使用。

由于我们使用add,show,hide去加快切换速度。每个页面的Fragment在切换的时候都没有销毁。而是隐藏的起来。当切换回来的时候在显示出来。
这就会出现一个问题,当用户旋转屏幕或是重History中运行已经被系统杀掉home activity的这个应用时。 会出现重叠现象。
重叠的原因是:
当用户旋转屏幕的时候,系统需要让当前的activity重新加载layout等信息,所以当前activity的onCreate会被重新调用。这是由于FragmentManager中的Fragment
仍是有效,当重建当前Activity的时候,就会导致在FragmentManager中增加了重复的Fragment,所以出现重叠。

解决这个问题的方法是我们要在系统调用 onSaveInstanceState的时候将FragmentManager中的所有Fragment都清理掉。
这样就不会出现重叠现象。




你可能感兴趣的:(android,开发学习)