Android基础之Fragment详解

一.定义

Fragment 表示 Activity中的行为或用户界面部分.

二.生命周期

1.onAttach

源码注释: 
called once the fragment is associated with its activity.

当fragment第一次和它的activity开始关联时回调此方法.

2.onCreate

源码注释:
called to do initial creation of the fragment

系统在初始化创建fragment时回调的方法

3.onCreateView

源码注释:
creates and returns the view hierarchy associated with the fragment.

系统在首次绘制fragment的用户界面时调用的方法,
返回的view 必须是Fragment布局的根视图,也可以是null.

4.onActivityCreated

源码注释:
tells the fragment that its activity has
completed its own {@link Activity#onCreate Activity.onCreate()}

告诉Fragment它依赖的Activity已经完成了onCreate方法. 我们可以在这里调用在Activity的onCreate方法中初始化的一些属性.

5.onViewStateRestored

源码注释:
tells the fragment that all of the saved state of its view hierarchy has been restored

告诉Fragment View的一些状态已经被恢复(比如check box 哪条被选中), 

6.onStart

源码注释:
Called when the Fragment is visible to the user.

当Fragment可以被用户看见时调用(此时还不能与用户交互)

7.onResume

源码注释:
Called when the fragment is visible to the user and actively running.

当Fragment可以被用户看见并可以交互时调用

8.onPause

源码注释:
Called when the Fragment is no longer resumed.

当Fragment不可以和用户进行交互时调用

9.onStop

源码注释:
 fragment is no longer visible to the user either because its activity is being stopped or a fragment operation is modifying it in the activity.

当Framgment不可见时候调用,可能是所属的Acitivty不可见或者 Fragment的operation在Acitivty中被修改

10.onDestroyView

源码注释:
allows the fragment to clean up resources
associated with its View.

允许Fragment 清理相关View的资源

11.onDestroy

源码注释:
called to do final cleanup of the fragment's state

当Fragment不再被使用时调用,清理Fragment的状态

12.onDetach

源码注释:
called immediately prior to the fragment no longer being associated with its activity

当Fragment与Activity解除关系时调用.

三.创建Fragment

1.如何想Acitivty中添加Fragment

(1) 在Activity布局文件中声明Fragment

`<?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" />

</LinearLayout>`

android:name 属性是 指定要在布局中实例化的Fragment类

(2)在代码中将Fragment添加在现有的某个ViewGroup

eg:

FragmentManager fragmentManager = getFragmentManager(); 
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); //创建事务

ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment); 
fragmentTransaction.commit(); //提交事务

2.管理Fragment

调用Activity中的fragment,必须使用FragmentManager

常用API:

(1)通过findFragmentById()(Activtiy布局中提供UI的Fragment)或者findFragmentByTag()(提供或者不提供UI的fragment) 获取Activity中的Fragment

(2)通过 popBackStack()(模拟用户发出的返回命令)将fragment从返回栈中弹出

(3)通过addOnBackStackChangedListener()注册一个监听返回栈变化的监听器

3.执行Fragment事务

eg:
将一个fragment替换成另一个fragment,并在返回栈中保留先前状态

`// 创建新的fragment和事务
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();

// 替换掉原来的fragment(如果有)
// 添加事务到返回栈中
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// 提交事务
transaction.commit();`

注意事项:

(1) 必须最后调用commit()

(2) 如果想统一容器中添加多个fragment,那么添加fragment的顺序将决定它们在图层结构中的出现顺序

(3) 在每个fragment事务提交前,可以调用setTransition()来应用过渡动画

4.FragmentPagerAdapter和FragmentStatePagerAdapter的区别

  • FragmentPagerAdapter

    • (1) 销毁视图,不销毁实例
      • 在实例化fragment时,会优先从FragmentManager中取出缓存的fragment.
      • 如果实例不存在,则会创建fragment,开始一个fragment的生命周期.
      • 如果取到了缓存的fragment,则会将这个fragment重新attach,然后走fragment的onCreateView
    • (2) 状态保存 空实现
      • FragmentPagerAdapter 在saveState方法中空实现
  • 总结: FragmentPagerAdapter,每次切换页面的时候会保留fragment在内存,只是detach调用,适合页面少的场景,常驻内存.

  • FragmentStatePagerAdapter

    • (1) 销毁实例
      • 在成员变量中设置两个集合,第一个集合用来保存fragment.destroyItem时候,会从集合中移除fragment,实例化fragment时,如果不存在那么走 getItem()方法
      • 另一个集合保存的是fragment的state,destroyItem时会保存销毁fragment的状态,在实例化fragment时候取出缓存fragment的state,并未getItem返回的fragment赋值.
    • (2) 状态保存 有代码逻辑实现
      • FragmentStatePagerAdapter 在saveState方法中进行了状态保存
  • 总结: FragmentPagerAdapter,每次切换页面的时候不会保留fragment在内存,调用remove方法,适合页面多的场景,不断重建销毁.

四.无UI的Fragment

1.定义

就是没有视图布局的Fragment,可以用做后台工作线程.

2.步骤

(1)使用add(Fragment,String)从Activity中添加fragment. 这里的 String字符串是为fragment提供一个唯一的"标识"

(2)有了这个标识,我们想从Activity中获取fragment可以使用 findFragmentByTag()找到这个fragment

五.Fragment的通信

1.Fragment中调用Actiivty中的方法

(1) 如何获取到Activity的引用

  • getActiivty()获取到对应Acitivity的引用

2.所在Activity嗲用Fragment的方法

(1) 如何获取Fragment的引用

  • findFragmentByTag()或者findFragmentById()获取到对应Fragment的引用

3. 在Fragment中调用另外一个Fragment的方法

(1) getSupportFragmentManager()

  • 首先拿到所属Activity的引用
  • 然后获取getSupportFragmentManager()
  • 最后根据findFragmentByTag()或者findFragmentById()获取到对应fragment的引用

(2) 回调的方式

  • 创建一个接口,包含所需传递的数据类型的参数
  • 定义接口实例,在事件中通过接口实例去调用接口方法
  • 创建一个静态的方法提供接口的注册
  • 调用函数注册实现方法,如果调用了接口方法,就会在调用方法出接受到数据.

(3) 使用本地广播

  • LocalBroadcastManager

(4) 事件总线

  • EventBus

六.Fragment 的切换方式

1.add()& remove() 或者replace()

  • add()加入fragment时会触发 onAttach(),
  • remove()fragment后,fragment状态不会被保存
  • replace()替换后,会将之前的fragment的view从viewtree中删除

2.hide()&show()

  • hide()只是隐藏了fragment中的view,并没有将view从viewtree中删除
  • show() 将隐藏的fragment显示

3.detach()和attach()

  • 使用attach()不会触发onAttach()
  • detach()后,fragment的状态依然保持,再使用attach()时会再次调用onCreateView来重绘视图.

七.懒加载,参数的传递与保存

1.原因

  • 一般用在ViewPager+Fragment的场景中, 因为
    ViewPager有个预加载机制,会提前加载fragment两边的fragment. 如果两个fragment中加载数据操作比较耗时,那么会占用大量内存,影响性能.

  • 采用懒加载,就是当打开某个fragment的时候,才去加载这个fragment的数据,而不是提前加载.优点在于不仅初始化速度变快,也可以节约流量.

2.LazyLoadFragmentDemo

`
public abstract class BaseLazyFragment extends Fragment {
private static final String TAG = BaseLazyFragment.class.getSimpleName();
private boolean isPrepared;

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    initPrepare();
}


/**
 * 第一次onResume中的调用onUserVisible避免操作与onFirstUserVisible操作重复
 */
private boolean isFirstResume = true;

@Override
public void onResume() {
    super.onResume();
    if (isFirstResume) {
        isFirstResume = false;
        return;
    }
    //切换界面回来,再次加载数据
    if (getUserVisibleHint()) {
        onUserVisible();
    }
}

@Override
public void onPause() {
    super.onPause();
    if (getUserVisibleHint()) {
        onUserInvisible();
    }
}

private boolean isFirstVisible = true;
private boolean isFirstInvisible = true;

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        if (isFirstVisible) {
            isFirstVisible = false;
            initPrepare();
        } else {
            onUserVisible();
        }
    } else {
        if (isFirstInvisible) {
            isFirstInvisible = false;
            onFirstUserInvisible();
        } else {
            onUserInvisible();
        }
    }
}

public synchronized void initPrepare() {
    if (isPrepared) {
        onFirstUserVisible();
    } else {
        isPrepared = true;
    }
}

/**
 * 第一次fragment可见(进行初始化工作)
 */
public abstract void onFirstUserVisible();

/**
 * fragment可见(切换回来或者onResume)
 */
public abstract void onUserVisible();

/**
 * 第一次fragment不可见(不建议在此处理事件)
 */
public abstract void onFirstUserInvisible();

/**
 * fragment不可见(切换掉或者onPause)
 */
public abstract void onUserInvisible();

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值