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

来源:互联网 发布:游戏秀 录制软件 编辑:程序博客网 时间:2024/06/05 23:04

1.现状:

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

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

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    app:layout_behavior="@string/appbar_scrolling_view_behavior"    tools:context="com.xiaohui.androidhome.tabnavigationbar.MainActivity"    tools:showIn="@layout/app_bar_main">    <FrameLayout        android:id="@+id/container"        android:layout_width="match_parent"        android:layout_height="match_parent">    </FrameLayout></RelativeLayout>

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

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

fragmentManager.beginTransaction().replace(R.id.container, new HomeFragment()).commit();
</pre><pre style="font-family:"DejaVu Sans Mono"; font-size:9pt; background-color:rgb(255,255,255)">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都清理掉。
这样就不会出现重叠现象。

1 0