fragment notes##

fragment相关内容包括

基本定义与使用

回退栈内部实现

fragment通信(与activity 与fragment)

DialogFragment

VP + Fragment

嵌套Fragment

懒加载

基本定义与使用(5个)

fragment依赖于Activity,不能独立存在

一个Activity可以有多个Fragment

一个Fragment可以被多个Activity复用

Fragment有自己的生命周期,并能接受输入事件

能在Activity运行时动态添加或删除Fragment

Fragment优势:(3个)

1.模块化Modularity

从此不用在一个Activity写所有的代码。而是把代码写在各自的Fragment中。

2.可重用Resuability

多个Activity可复用同一个Fragment

3.可适配Adaptability

根据硬件的屏幕尺寸和方向选择不同的布局

Fragment核心类:(3个)

Fragment:任何Fragment的基类

FragmentManager:管理Fragment。FM是抽象类,实现类是FragmentManagerImpl

FragmentTransaction:对Fragment操作,包括添加,删除登需要通过事务处理。FT是抽象类,实现类是BackStackRecord.

Nested Fragment(Fragment内部嵌套Fragment的能力)是Android 4.2提出的.support-fragment库可以兼容到1.6。通过getChildFragmentManager()能够获得管理子Fragment的FragmentManager,在子Fragment中可以通过getParentFragment()获得父Fragment。

	public class Fragment1 extends Fragment{

private static String ARG_PARAM = "param_key";

private String mParam;
private Activity mActivity; public void onAttach(Context context) {
mActivity = (Activity) context;
mParam = getArguments().getString(ARG_PARAM); //获取参数
} public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_1, container, false);
TextView view = root.findViewById(R.id.text);
view.setText(mParam);
return root;
} public static Fragment1 newInstance(String str) {
Fragment1 frag = new Fragment1();
Bundle bundle = new Bundle();
bundle.putString(ARG_PARAM, str);
fragment.setArguments(bundle); //设置参数
return fragment;
}
}

Fragment有很多可以复写的方法,其中最常用的就是onCreateView(),该方法返回Fragment的UI布局,需要注意的是inflate()的第三个参数是false,因为在Fragment内部实现中,会把该布局添加到container中,如果设为true,那么就会重复做两次添加,则会抛如下异常

Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

创建Fragment时传参必须使用setArguments(Bundle b)###

如果在创建Fragment时要传入参数,必须要通过setArguments(Bundle bundle)方式添加,而不建议通过为Fragment添加带参数的构造函数,

原因:

因为通过setArguments()方式添加,在由于内存紧张导致Fragment被系统杀掉并恢复(re-instantiate)时能保留这些数据。

这点很重要。否则可能导致严重后果!!!

取参数在onAttached()中取,context上下文也要在该处取###

我们可以在Fragment的onAttach()中通过getArguments()获得传进来的参数,并在之后使用这些参数。如果要获取Activity对象,不建议调用getActivity(),而是在onAttach()中将Context对象强转为Activity对象。

在Activity中添加Fragment的方式有两种:

静态添加:在xml中通过的方式添加,缺点是一旦添加就不能在运行时删除。

动态添加:运行时添加,这种方式比较灵活,因此建议使用这种方式。

虽然Fragment能在XML中添加,但是这只是一个语法糖而已,Fragment并不是一个View,而是和Activity同一层次的

1.Activity提供容器

首先Activity需要有一个容器存放Fragment,一般是FrameLayout,因此在Activity的布局文件中加入FrameLayout:

然后在onCreate()中,通过以下代码将Fragment添加进Activity中。

if (bundle == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, Fragment1.newInstance("hello world"), "f1")
//.addToBackStack("fname")
.commit();
}

需要注意的有如下几点:

因为我们使用了support库的Fragment,因此需要使用getSupportFragmentManager()获取FragmentManager。

add()是对Fragment众多操作中的一种,还有remove(), replace()等,第一个参数是根容器的id(FrameLayout的id,即”@id/container”),第二个参数是Fragment对象,第三个参数是fragment的tag名,指定tag的好处是后续我们可以通过Fragment1 frag = getSupportFragmentManager().findFragmentByTag("f1")从FragmentManager中查找Fragment对象。

在一次事务中,可以做多个操作,比如同时做add().remove().replace()。

commit()操作是异步的。内部通过mManager.enqueueAction()加入处理队列。

对应的同步方法为commitNow(),commit()内部会有checkStateLoss()操作,如果开发人员使用不当(比如commit()操作在onSaveInstanceState()之后),可能会抛出异常解决方案和产生分析

commitAllowingStateLoss()方法则是不会抛出异常版本的commit()方法,但是尽量使用commit(),而不要使用commitAllowingStateLoss()。

addToBackStack("fname")是可选的。FragmentManager拥有回退栈(BackStack),类似于Activity的任务栈,如果添加了该语句,就把该事务加入回退栈,当用户点击返回按钮,会回退该事务(回退指的是如果事务是add(frag1),那么回退操作就是remove(frag1));如果没添加该语句,用户点击返回按钮会直接销毁Activity。

Fragment有一个常见的问题,即Fragment重叠问题,这是由于Fragment被系统杀掉,并重新初始化时再次将fragment加入activity,因此通过在外围加if语句能判断此时是否是被系统杀掉并重新初始化的情况。

Fragment有个常见的异常:

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1341)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1352)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)

从上面看到,先从mAdded中查找是否有该Fragment,如果没找到,再从mActive中查找是否有该Fragment。mAdded是已经添加到Activity的Fragment的集合,mActive不仅包含mAdded,还包含虽然不在Activity中,但还在回退栈中的Fragment。

该异常出现的原因是:commit()在onSaveInstanceState()后调用。首先,onSaveInstanceState()在onPause()之后,onStop()之前调用。onRestoreInstanceState()在onStart()之后,onResume()之前。

因此避免出现该异常的方案有:

不要把Fragment事务放在异步线程的回调中,比如不要把Fragment事务放在AsyncTask的onPostExecute(),因此onPostExecute()可能会在onSaveInstanceState()之后执行。

逼不得已时(即一定会出现事务丢失时)使用commitAllowingStateLoss()。

FragmentTransaction有一些基本方法,下面给出调用这些方法时,Fragment生命周期的变化:

add(): onAttach()->…->onResume()。

remove(): onPause()->…->onDetach()。

replace(): 相当于旧Fragment调用remove(),新Fragment调用add()。

show(): 不调用任何生命周期方法,调用该方法的前提是要显示的Fragment已经被添加到容器,只是纯粹把Fragment UI的setVisibility为true。

hide(): 不调用任何生命周期方法,调用该方法的前提是要显示的Fragment已经被添加到容器,只是纯粹把Fragment UI的setVisibility为false。

detach(): onPause()->onStop()->onDestroyView()。UI从布局中移除,但是仍然被FragmentManager管理。

attach(): onCreateView()->onStart()->onResume()。

Fragment实现原理与BackStack

Fragment向Activity传递数据

首先,在Fragment中定义接口,并让Activity实现该接口

在Fragment的onAttach()中,将参数Context强转为OnFragmentInteractionListener对象:

**FABridge

**

由于通过接口的方式从Fragment向Activity进行数据传递比较麻烦,需要在Fragment中定义interface,并让Activity实现该interface,FABridge通过注解的形式免去了这些定义。

Activity向Fragment传递数据

Activity向Fragment传递数据比较简单,获取Fragment对象,并调用Fragment的方法即可,比如要将一个字符串传递给Fragment,则在Fragment中定义方法

Fragment之间通信

由于Fragment之间是没有任何依赖关系的,因此如果要进行Fragment之间的通信,建议通过Activity作为中介,不要Fragment之间直接通信。

DialogFragment

DialogFragment是Android 3.0提出的,代替了Dialog,用于实现对话框。他的优点是:即使旋转屏幕,也能保留对话框状态。

Fragment(一)--Fragment用法常见问题的更多相关文章

  1. RadioGroup+Fragment 使用Fragment的add()方法,防止使用replace每次都重新加载页面,造成资源浪费

    radiogroup+fragment是很常用的主页导航控件,之前为了代码简便一直使用的replace()替换fragment,代码如下: getSupportFragmentManager().be ...

  2. android fragment嵌套fragment出现的问题:no activity

    package com.example.fragmentNavigation2.fragment; import android.content.Context; import android.os. ...

  3. 关于Fragment与Fragment、Activity通信的四种方式

    一直想总结一下Fragment与Fragment.Activity通信的问题,今天有时间一共总结了三种,权当抛砖引玉,如果大家还有更好的方式来实现Fragment和Fragment.Activity的 ...

  4. activity 嵌套一级fragment,一级fragment嵌套二级fragment,在一级fragment中刷新二级fragment中的UI

    今天遇到挺纠结的问题,由于产品设计的问题,技术上涉及到activity 嵌套一级fragment,一级fragment嵌套二级fragment,在一级fragment中刷新二级fragment中的UI ...

  5. TabActivity 、fragemnt+fragment 和 Fragment+Viewpager 优缺点

    1 TabActivity : 1 过时了 . 2 activity . 是作为android的四大组件...                   重量级的家伙   ViewGroup   : 特别麻 ...

  6. fragment基础 fragment生命周期 兼容低版本

    fragment入门 ① 创建一个类继承Fragment 重写oncreateView方法 public class FirstFragment extends Fragment { @Overrid ...

  7. Fragment学习(二): 管理Fragment和Fragment通讯

    一. 管理Fragment 首先,如果你想在Android3.0及以下版本使用Fragment,你必须引用android-support-v4.jar这个包 然后你写的activity不能再继承自Ac ...

  8. Fragment 嵌套Fragment注意事项

    最近项目新功能需要在垂直方方向可以循环滚动,并且水平方向也可以水平循环滚动,并且可以定位到指定item上.很自然的想到了ViewPager和 VerticalViewPager来解决项目需求,UI的大 ...

  9. Fragment的基本用法

    一.Fragment主要用到的API: 1.Fragment 类-----用来创建碎片 2.FragmentManager 类 ----为管理Activity中Fragment,用于Activity与 ...

随机推荐

  1. Microsoft Speech SDK开发包 使用

    下载开发包.我们首先从微软的官网上面下载开发包,下载地址如下: http://www.microsoft.com/en-us/download/details.aspx?id=10121我们主要下载三 ...

  2. HDU 1394 树状数组+离散化求逆序数

    对于求逆序数问题,学会去利用树状数组进行转换求解方式,是很必要的. 一般来说我们求解逆序数,是在给定一串序列里,用循环的方式找到每一个数之前有多少个比它大的数,算法的时间复杂度为o(n2). 那么我们 ...

  3. bzoj4289

    最短路 很容易想到边和边之间连边,但是这样菊花图就完蛋了 我们想办法优化一下,能不能不要每条边都连. 考虑查分,把一个点的出边串起来,这样就行了,每条无向边拆成两条就能保证了 #include< ...

  4. SpringMVC注解说明

    @controller 通过@controller标注即可将class定义为一个controller类. @RequestMapping value 表示需要匹配的url的格式. method 表示所 ...

  5. asp.net中FileUpload得到上传文件的完整路径

    asp.net中FileUpload得到上传文件的完整路径 Response.Write("完整路径:" + Server.MapPath(FileUpload1.PostedFi ...

  6. python学习笔记——Thread常用方法

    Thread对象中的一些方法: 以前说过多线程,用到threading模块中的Thread对象,其中的start和run方法比较熟悉了,start()是重载了Thread对象中的run方法,其实作用还 ...

  7. Excel的poi缓存问题

    Excel的poi缓存问题 背景: 最近工作需要,需要完成生成新的Excel,然后从Excel中读取包含公式的文本内容. 问题: 当程序中修改公式对应的单元格数据变化时,公式获取的值仍然还是原来的值, ...

  8. 2.1-2.2 HBase数据存储

    一.HBase数据检索流程 一篇介绍HBase数据读写流程的解析的博文:http://hbasefly.com/2016/12/21/hbase-getorscan/?wsfatm=uqvhl3 1. ...

  9. c++中IO输入输出流总结<二>

    1 文件的打开和关闭 1.1 定义流对象 ifsteam iflie;//文件输入流对象 ifsteam iflie;//文件输出流对象 fsteam iflie;//文件输入输出流对象 1.2 打开 ...

  10. SQL Server服务器连接配置

    一.首先确保服务器能在本地打开数据库 如果碰到本地无法连接到数据库,首先要确认上图中两个服务是否开启 二.其次,要配置远端可连接的用户 如图,配置数据库[属性]中[安全性]为混合验证,勾中允许远程连接 ...