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

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都清理掉。
这样就不会出现重叠现象。
--------------------- 
作者:yuxiaohui78 
来源:CSDN 
原文:https://blog.csdn.net/yuxiaohui78/article/details/51711831 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值