Android总结 - Fragment

Fragment生命周期

Fragment的生命周期跟Activity类似,跟Activity一样,Fragment也有的生命状态。
这里写图片描述

  • Created
     onAttach():当Fragment第一次attach到Activity。
     onCreate():Fragment的初始化创建,这个回调函数调用的时候,Activity处于create的过程中,不要处理跟Activity相关的东西,比如content view。
     onCreateView():实例化Fragment的View并返回。
     onViewCreated():onCreateView()完成之后,会里面回调这个函数。
     onActivityCreated():当Activity的onCreate()完成和Fragment的View被初始化之后,回调这个函数。
  • Started
     onStart():跟Activity同步,当Activity的处于start状态时,Fragment的onStart()被调用。
  • Resumed
     等同于Activity的Resumed的状态。当Activivty的onResume被调用时,Fragment的onResume()同时被调用。
  • Paused
    等同于Activity的Paused的状态。当Activivty的onPause被调用时,Fragment的onPause()同时被调用。
  • Stopped
     等同于Activity的Stopped状态,当Activivty的onStop被调用时,Fragment的onStop()同时被调用。
  • Destroyed
     onDestroyView():之前onCreateView创建出来的View被移除,下次Fragment显示的时候需要重新创建一个View。
     onDestroy():当Fragment不再使用的时候会调用onDestroy。
     onDetach(): Fragment从Activity中移除,detach。

跟Activity一样, 可以使用Bundle来保存状态,防止Activity被杀掉之后,我们需要恢复fragment的状态当Activity 重建之后。可以通过调用fragment’s onSaveInstanceState()函数保存,在这几个函数中恢复onCreate(), onCreateView(), or onActivityCreated()。

Fragment使用

  • 通过XML Layout文件
    有三种方法为Fragment提供ID:
     android:id属性:唯一的id
     android:tag属性:唯一的字符串
     如果上面两个都没提供,系统使用容器view的ID。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment android:name="com.example.news.ArticleListFragment"
            android:id="@+id/list"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
    <fragment android:name="com.example.news.ArticleReaderFragment"
            android:id="@+id/viewer"
            android:layout_weight="2"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
</LinearLayout>
  • 通过代码动态添加
    动态使用Fragment就是手动在代码中添加、替换、删除Fragment。获取FragmentManager,通过事务添加或者删除Fragment,设置默认显示Fragment,开启事务transaction,提交事务。
FragmentManager fragmentManager = getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();

管理Fragments

Fragment是通过 FragmentManager来管理,通过getFragmentManager()来获取,通过FragmentManager可以做以下事情:

  • 通过findFragmentById()或者findFragmentByTag()来获取Fragment
  • 通过popBackStack()出栈back stack。
  • 通过addOnBackStackChangedListener()来注册监听back stack的变化。

FragmentTransaction事务来管理Fragment的变化,一个事务可以处理多个事情,比如add(), remove(), and replace()。之后调用commit来提交这个事务。
在提交事务之前,可以通过“addToBackStack()”把事务加到back stack中,这个back stack通过Activity来管理。通过返回键可以反转事务然后返回到前一个fragment的状态。
举例使用addToBackStack()

// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();

// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// Commit the transaction
transaction.commit();

注意:我们必须在activity保存状态前提交事务。如果是在activity保存状态之后提交事务,就是抛一个Exception,这是因为activity的状态会被丢失在事务提交之后。这个情况下使用commitAllowingStateLoss()来表示你可以放弃这次事务的提交。

Transaction的几个方法执行流程:
transaction.show(fragment),transaction.hide(fragment), 显示或者隐藏Fragment,onHiddenChanged()回调函数会被调用;

API 23上不会调用onAttach方法,需要在Support包上使用。
remove方法执行后Fragment的回调流程:
onPause -> onStop -> onDestroyView -> onDestroy -> onDetach
add方法执行后的Fragment回调函数:
onAttach -> onCreate-> onCreateView -> onActivityCreated -> onStart -> onResume
detach方法执行后的Fragment回调函数,Fragment不会销毁:
onPause -> onStop -> onDestroyView
attach方法执行后的Fragment回调函数:
onCreateView -> onActivityCreated -> onStart -> onResume

不添加到back stack, replace方法执行后的回调函数,replace相当于向调用remove,再调用add:
旧Fragment:onPause -> onStop -> onDestroyView -> onDestroy -> onDetach
新Fragment:onAttach -> onCreate-> onCreateView -> onActivityCreated -> onStart -> onResume

添加到back stack, replace方法执行后的回调函数,旧Fragment不会销毁:
onPause -> onStop -> onDestroyView
调用popBackStack,Fragment回调流程:
onPause -> onStop -> onDestroyView -> onDestroy -> onDetach

setCustomAnimations方法可以设置Fragment在FragmentManager中的切换动画。参考:https://developer.android.com/training/animation/cardflip.html?hl=id

与Activity交互

Fragment可以通过getActivity()来获取到关联的Activity。
Activity可以通过FragmentManager调用findFragmentById() or findFragmentByTag()来获取相关的Fragment。

给Activity创建一个事件回调函数

如果Fragment需要与Activity共享事件,可以在Fragmeng中申明一个接口,然后相关的Activity来实现。在onAttach的时候,把Activity赋值给Fragment中的接口变量。

public static class FragmentA extends ListFragment {
    ...
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnArticleSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
        }
    }
    ...

    ...
    // Container Activity must implement this interface
    public interface OnArticleSelectedListener {
        public void onArticleSelected(Uri articleUri);
    }
    ...
}

Fragment在ViewPager中的生命周期

使用FragmentPagerAdapter

FragmentPagerAdapter把每一页都表现为一个Fragment,并且会被保留在fragment manager 中。
FragmentPagerAdapter比较适合于少量静态Fragment之间的切换, 比如一套Tab。每一个用户浏览过的Fragment会被保存在内存中,即使它的view已经destroy了。这会导致 使用大量的内存,因为Fragment的实体会被保存到任意的状态。

假设ViewPager中有三个Fragment,分别为A,B,C。
第一次进入ViewPager时:ViewPager会初始化两个Fragment,也就是A和B。那么A,B此时的生命周期调用流程为:
A: setUserVisibleHint(isVisibleToUser=false)->onAttach ->onCreate -> setUserVisibleHint(isVisibleToUser=true) -> onCreateView -> onActivityCreated -> onStart -> onResume
B: setUserVisibleHint(isVisibleToUser=false)->onAttach ->onCreate -> onCreateView -> onActivityCreated -> onStart -> onResume

当ViewPager滑动一页的时候,也就是当前页从A到了B,那么A、B、C的生命周期的调用流程为:
A:setUserVisibleHint(isVisibleToUser=false)
B: setUserVisibleHint(isVisibleToUser=true)
C:setUserVisibleHint(isVisibleToUser=false)->onAttach ->onCreate -> onCreateView -> onActivityCreated -> onStart -> onResume

当ViewPager的当前页从B换到C的时候,那么A、B、C的生命周期的调用流程为:
A:onPause -> onStop -> onDestroyView
B:setUserVisibleHint(isVisibleToUser=false)
C:setUserVisibleHint(isVisibleToUser=true)
可以看出ViewPager默认只会保存两个Fragment。

当ViewPager的当前页从C换到B的时候,那么A、B、C的生命周期的调用流程为:
A: setUserVisibleHint(isVisibleToUser=false) -> onCreateView -> onActivityCreated -> onStart -> onResume
B:setUserVisibleHint(isVisibleToUser=true)
C:setUserVisibleHint(isVisibleToUser=false)

当ViewPager的当前页为C时,我们把Activity切换到后台,按下Home键,那么A、B、C的生命周期的调用流程为:
A:什么都不调用。
B:onPause -> onSaveInstanceState -> onStop
C:onPause -> onSaveInstanceState -> onStop

当Activity又切到前台后,那么A、B、C的生命周期的调用流程为:
A:什么都不调用
B:onStart -> onResume
C:onStart -> onResume

当ViewPager的当前页为C时,退出Activity那么A、B、C的生命周期的调用流程为:
A:onDestroy -> onDetach
B:onPause -> onStop -> onDestroyView -> onDestroy -> onDetach
C:onPause -> onStop -> onDestroyView -> onDestroy -> onDetach


使用FragmentStatePagerAdapter

FragmentStatePagerAdapter使用一个Fragment管理每个page。这个类同时也操控保存和恢复fragment的状态。
这个类适合于有大量pages的时候,比如一个列表视图。当page不可见的时候,它们的fragment也会被销毁,只会保留被保存的状态。 这种模式比FragmentPagerAdapter 使用更少的内存,但是在切换的时候会有更多的消耗。

当ViewPager的当前页从B换到C的时候,那么A、B、C的生命周期的调用流程为:
A:onSaveInstanceState -> onPause -> onStop -> onDestroyView -> onDestroy -> onDetach
B:setUserVisibleHint(isVisibleToUser=false)
C:setUserVisibleHint(isVisibleToUser=true)
可以看出,A Fragment会被remove掉,比FragmentPagerAdapter多调用了三个函数A:onSaveInstanceState 、onDestroy 和onDetach。

当ViewPager的当前页从C换到B的时候,那么A、B、C的生命周期的调用流程为:
A: setUserVisibleHint(isVisibleToUser=false) -> onAttach -> onCreate -> onCreateView -> onActivityCreated -> onStart -> onResume
B:setUserVisibleHint(isVisibleToUser=true)
C:setUserVisibleHint(isVisibleToUser=false)

ViewPager的缓存

通过函数setOffscreenPageLimit(int limit)可以设置Viewpager默认帮助缓存current page前后各缓存limit个page

ViewPager动画

通过使用 ViewPager.PageTransformer 可以现在Fragment在ViewPager中的切换动画。
参考:https://developer.android.com/training/animation/screen-slide.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值