【Android】Fragment真正意义上的onResume和onPause

前言

Fragment虽然有onResume和onPause的,但是这两个方法是Activity的方法,调用时机也是与Activity相同,和ViewPager搭配使用这个方法就很鸡肋了,根本不是你想要的效果,这里介绍一种方法。

声明

欢迎转载,但请保留文章原始出处:) 
博客园:http://www.cnblogs.com
农民伯伯: http://over140.cnblogs.com

正文

继承setUserVisibleHint方法:


    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
            //相当于Fragment的onResume
        } else {
            //相当于Fragment的onPause
        }
    }

代码说明:

通过阅读ViewPager和PageAdapter相关的代码,切换Fragment实际上就是通过设置setUserVisibleHint和setMenuVisibility来实现的,调用这个方法时并不会释放掉Fragment(即不会执行onDestoryView)。

 
 
 

【Android】保存Fragment切换状态

前言

一般频繁切换Fragment会导致频繁的释放和创建,如果Fragment比较臃肿体验就非常不好了,这里分享一个方法。

声明

欢迎转载,但请保留文章原始出处:) 
博客园:http://www.cnblogs.com
农民伯伯: http://over140.cnblogs.com

正文

一、应用场景

1、不使用ViewPager

2、不能用replace来切换Fragment,会导致Fragment释放(调用onDestroyView)

二、实现

1、xml


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >     <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight="1.0" >
    </FrameLayout>     <RadioGroup
        android:id="@+id/main_radio"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:gravity="bottom"
        android:layout_marginBottom="-6dp"
        android:orientation="horizontal" >         <RadioButton
            android:id="@+id/radio_button0"
            style="@style/main_tab_bottom"
            android:drawableTop="@drawable/bottom_1" />         <RadioButton
            android:id="@+id/radio_button1"
            style="@style/main_tab_bottom"
            android:drawableTop="@drawable/bottom_2" />         <RadioButton
            android:id="@+id/radio_button2"
            style="@style/main_tab_bottom"
            android:drawableTop="@drawable/bottom_3" />         <RadioButton
            android:id="@+id/radio_button3"
            style="@style/main_tab_bottom"
            android:drawableTop="@drawable/bottom_4" />         <RadioButton
            android:id="@+id/radio_button4"
            style="@style/main_tab_bottom"
            android:drawableTop="@drawable/bottom_5" />
    </RadioGroup> </LinearLayout>

代码说明:

非常常见的底部放5个RadioButton,点击切换不同的Fragment。

2、Activity

为RadioButton设置setOnCheckedChangeListener事件,其他代码:


    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if (isChecked) {
            Fragment fragment = (Fragment) mFragmentPagerAdapter.instantiateItem(mContainer, buttonView.getId());
            mFragmentPagerAdapter.setPrimaryItem(mContainer, 0, fragment);
            mFragmentPagerAdapter.finishUpdate(mContainer);
        } 
    }     private FragmentPagerAdapter mFragmentPagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {         @Override
        public Fragment getItem(int position) {
            switch (position) {
            case R.id.radio_button1:
                return new Fragment1();
            case R.id.radio_button2:
                return new Fragment2();
            case R.id.radio_button3:
                return new Fragment3();
            case R.id.radio_button4:
                return new Fragment4();
            case R.id.radio_button0:
            default:
                return new Fragment0();
            }
        }         @Override
        public int getCount() {
            return 5;
        }
    };

代码说明:

instantiateItem从FragmentManager中查找Fragment,找不到就getItem新建一个,setPrimaryItem设置隐藏和显示,最后finishUpdate提交事务。

mContainer就是xml中的FrameLayout。

三、FragmentPagerAdapter核心代码


    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }         final long itemId = getItemId(position);         // Do we already have this fragment?
        String name = makeFragmentName(container.getId(), itemId);
        Fragment fragment = mFragmentManager.findFragmentByTag(name);
        if (fragment != null) {
            if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
            mCurTransaction.attach(fragment);
        } else {
            fragment = getItem(position);
            if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
            mCurTransaction.add(container.getId(), fragment,
                    makeFragmentName(container.getId(), itemId));
        }
        if (fragment != mCurrentPrimaryItem) {
            fragment.setMenuVisibility(false);
            fragment.setUserVisibleHint(false);
        }         return fragment;
    }     @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }
        if (DEBUG) Log.v(TAG, "Detaching item #" + getItemId(position) + ": f=" + object
                + " v=" + ((Fragment)object).getView());
        mCurTransaction.detach((Fragment)object);
    }     @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        Fragment fragment = (Fragment)object;
        if (fragment != mCurrentPrimaryItem) {
            if (mCurrentPrimaryItem != null) {
                mCurrentPrimaryItem.setMenuVisibility(false);
                mCurrentPrimaryItem.setUserVisibleHint(false);
            }
            if (fragment != null) {
                fragment.setMenuVisibility(true);
                fragment.setUserVisibleHint(true);
            }
            mCurrentPrimaryItem = fragment;
        }
    }     @Override
    public void finishUpdate(ViewGroup container) {
        if (mCurTransaction != null) {
            mCurTransaction.commitAllowingStateLoss();
            mCurTransaction = null;
            mFragmentManager.executePendingTransactions();
        }
    }

FragmentPagerAdapter是support包自带的类。

四、注意

之前自己模拟ViewPager用attach、setMenuVisibility、setUserVisibleHint来控制Fragment的显示隐藏,经常会出现Fragment重叠现象,非常头疼,换了这个之后目前没有发现重叠现象。

五、文章后期维护

2013-12-01  上传示例代码:http://files.cnblogs.com/over140/SampleFragmentSwitch.zip

    @Override
    public void setMenuVisibility(boolean menuVisible) {
        super.setMenuVisibility(menuVisible);
        if (this.getView() != null)
            this.getView().setVisibility(menuVisible ? View.VISIBLE : View.GONE);
    }

重新做例子时发现自己也出不来效果了,后来发现少了这段代码。

2014-01-08 想实现本文的效果还是推荐直接使用ViewPager,通过自定义ViewPager禁用掉左右滑动和自动销毁即可,根据评论来看非正常情况下重影现象还是挺严重的。

结束

需要多看看源码,才能很好的解决问题。

fragment.setMenuVisibility setUserVisibleHint的更多相关文章

  1. Fragment的setUserVisibleHint方法实现懒加载,但setUserVisibleHint 不起作用?

    我们在做应用开发的时候,一个Activity里面可能会以viewpager(或其他容器)与多个Fragment来组合使用,而如果每个fragment都需要去加载数据,或从本地加载,或从网络加载,那么在 ...

  2. Fragment的setUserVisibleHint方法实现懒加载

    public abstract class LazyFragment extends Fragment {     protected boolean isVisible;     /**       ...

  3. 关于Fragment的setUserVisibleHint() 方法和onCreateView()的执行顺序

    1:setUserVisibleHint(boolean isVisibleToUser)的方法就很重要,根据方法名来看当前页面是否可见, 里面的boolean值就是判断当前页面是否可见的变量,所以大 ...

  4. setUserVisibleHint-- fragment真正的onResume和onPause方法

    现在越来越多的应用会使用viewpager+fragment显示自己的内容页,fragment和activity有很多共同点,如下图就是fragment的生命周期 但是fragment和activit ...

  5. Android setUserVisibleHint-- fragment真正的onResume和onPause方法

    这个情况仅适合与多个fragment之间切换时统计,而非activity和fragment同时交互,因当时项目为首页4个fargment时长统计,因此适合,经下面网友评论指出,特在这里写出此问题,因最 ...

  6. setUserVisibleHint的使用.执行顺序和viewPager.setOffscreenPageLimit(0)不管用还是默认会加载第二个fragment

    处理问题一:viewPager.setOffscreenPageLimit(0)不管用还是默认会加载第二个fragment的原因(源码解读); 处理问题二:setUserVisibleHint的使用场 ...

  7. 使用ViewPager切换Fragment时,防止频繁调用OnCreatView

    使用ViewPager切换Fragment,我原先使用系统自带的适配器FragmentPagerAdapter. 切换fragment时,频繁调用oncreatview(). 查看FragmentPa ...

  8. 【Android】保存Fragment切换状态

    前言 一般频繁切换Fragment会导致频繁的释放和创建,如果Fragment比较臃肿体验就非常不好了,这里分享一个方法. 声明 欢迎转载,但请保留文章原始出处:)  博客园:http://www.c ...

  9. ViewPager部分源码分析二:FragmentManager对Fragment状态的管理完成ViewPager的child添加或移出

    ViewPager维护child代码流程: 注:PagerAdapter 使用的是FragmentPagerAdapter类或者它的子类. viewPager.populate(): void pop ...

随机推荐

  1. Super超级ERP系统---(9)订单管理--订单拣货

    订单审核完成后,库房就可以开始备货,安排相应的人员去拣货了.订单拣货主要分为一次分拣和二次分拣,这里我们先看下一次分拣的流程.一次分拣就是根据订单去拣货,可以简单的理解为拿着一个订单,推着购物车,把当 ...

  2. 3.0 Windows和Linux双系统安装(3)

    3.0 Windows和Linux双系统安装(3) 3.1 精简的安装步骤如下:(如果已经有了前面两篇教程的安装经验,推荐看完3.1即可动手了) 双系统很多开发新人会用到,而且比起虚拟机好处是运行效率 ...

  3. OPPO R9sPlus MIFlash线刷TWRP Recovery ROOT详细教程

    教程转载来自 残芯此生不换  OPPO R9sPlus 目前最简单的刷Recovery root 方法,强烈推荐 新机想要刷第三方卡刷包的最简单过程是:           手机关机-->下载M ...

  4. WPF度量系統

    和Winform不同,WPF的度量單位不是像素,而是設備無關單位DIU,其大小總是1/96吋 那麽,WPF中一個寬度爲96的按鈕,到底是多少個像素呢? 答:取決於系統DPI. 計算公式爲:實際像素 = ...

  5. 2星|《腾讯产品法》:标题党,作者只有QQ手机助手的短期产品经验

    腾讯产品法(一本书读懂腾讯产品思维与运营方法,<腾讯传>作者吴晓波推荐) 全书是作者的一些产品设计与运营的经验.如果书名不误导读者,这本书的内容值3星. 基于书名的误导,读后比较失望,作者 ...

  6. java StringUtils

    /** * */ package com.sign.utils; import java.util.regex.Pattern; /** * @author Administrator * creat ...

  7. 微信小程序开发常用方法

    1.函数中访问data中的数据 _this.setData({ // 日历数据 signList: dataList, // 当前日期 todayDay: str }) 2.if判断 wx:if=&q ...

  8. centos7网卡重命名为ethx格式

    参考:https://www.cnblogs.com/zyd112/p/8143464.html CentOS 7 使用 eth0 这样的传统名称,那么在安装启动(pxe)时,按Tab键在下方输入以下 ...

  9. C#连接Oracle数据库的方法(System.Data.OracleClient、Oracle.DataAccess.Client也叫ODP.net、Oracle.ManagedDataAccess.dll)

    官方下载地址(ODP.net)(中文):http://www.oracle.com/technetwork/cn/topics/dotnet/downloads/index.html 官方下载地址(O ...

  10. python mysql连接池

    话不多说,直接撸代码 # coding=utf-8 from DBUtils.PooledDB import PooledDB import pymysql as mysql import trace ...