Android Fragment 使用详解
虽然网上有很多关于Fragment的文章,但我这里还是要写这篇笔记,因为我在编写程序的过程中发现了一个问题,至今未解决,希望得到大家的帮助;
PS:当我在Fragment中定义一个名为setIndex(int index)的方法之后,运行程序,就会报错(打印的错误信息显示错误为找不到这个Fragment对应的类),但当把这个方法的名称改为其它的名称之后,程序即可正常运行,我的api level为17和18;
先看看Fragment的生命周期方法,其实和Activity基本还是相似的,了解Activity的生命周期,再看Fragment的生命周期方法,也就比较容易理解;


先介绍相关概念
一、fragment通常作为宿主activity UI的一部分, 被作为activity整个view hierarchy的一部分被嵌入,相当于一个轻量级的Activity;
(一)、将一个fragment添加到layout,有两种方法。
1、在Layout文件中,添加一个Fragement对应的节点
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<fragment
android:id="@+id/main_mf"
android:name="com.dbo4.domain.MyFragement"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
- 为 android:id 属性提供一个唯一ID;
- 为 android:tag 属性提供一个唯一字符串;
- 如果以上2个你都没有提供, 系统使用容器view的ID.
2、使用FragmentManager将fragment添加到一个已经存在的ViewGroup
当activity运行的任何时候, 都可以将fragment添加到它的layout.只需简单的指定一个需要放置fragment的ViewGroup(通常为FrameLayout).FragmentManager提供了一个FragmentTransaction的API,以实现在activity中操作fragment事务(例如添加,移除,或代替一个fragment)。
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
然后可以使用 add() 方法添加一个fragment, 指定要添加的fragment, 和要插入的view.
MyFragment fragment = new MyFragment();
fragmentTransaction.add(R.id.xx_viewgroup, fragment);
fragmentTransaction.commit();
两个参数分别是要放入的ViewGroup, 由resource ID指定和需要添加的fragment。为了使改变生效,还须调用commit()提交事务.
(二)、如果需要Fragment显示菜单,可设置hasOptionsMenu = true;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
} @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.add("Ma").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add("Mb").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODOreturn super.onOptionsItemSelected(item);
}
二、FragmentManager
FragmentManager能够实现管理activity中fragment. 通过调用activity的getFragmentManager()取得它的实例.FragmentManager可以做如下一些事情:
1、使用findFragmentById() (适用于在layout中提供了一个UI的fragment)或findFragmentByTag()(适用于有或没有UI的fragment)获取activity中存在的fragment;
2、将fragment从后台堆栈中弹出, 使用 popBackStack() (模拟用户按下BACK 命令);
3、使用addOnBackStackChangeListener()注册一个监听后台堆栈变化的listener.
三、FragmentTransaction
FragmentTransaction提供了对fragment进行添加,移除,替换,以及执行其他操作的api。每一个事务都是同时要执行的一套变化.可以在一个给定的事务中设置你想执行的所有变化,使用诸如 add(), remove(), 和 replace(),然后, 要给activity应用事务, 还必须要调用 commit().
在调用commit()之前, 你可能想调用 addToBackStack(),将事务添加到一个fragment事务的back stack. 这个back stack由activity管理, 并允许用户通过按下 BACK 按键返回到前一个fragment状态.
ft = fm.beginTransaction();
ft.replace(R.id.cont, new Fragment2());
ft.addToBackStack("f2");
ft.commit();
/************************************/
ft = fm.beginTransaction();
ft.replace(R.id.cont, new Fragment3());
ft.commit();
通过调用 addToBackStack(), replace事务被保存到back stack, 因此用户可以回退事务,并通过按下BACK按键带回前一个fragment.
执行上面两个方法执行的Fragment2的生命周期方法为:
onAttach -- onCreate -- onCreateView -- onActivityCreated -- onStart -- onResume --
onPause -- onStop -- onDestoryView --
onCreateView -- onActivityCreated -- onStart -- onResume --
如果添加多个变化到事务(例如add()或remove())并调用addToBackStack(), 然后在调用commit()之前的所有应用的变化会被作为一个单个事务添加到后台堆栈, BACK按键会将它们一起回退.当执行一个移除fragment的事务时, 如果没有调用 addToBackStack(), 那么当事务提交后, 那个fragment会被销毁,并且用户不能导航回到它。反之,比如当移除一个fragment时,如果调用了 addToBackStack(), 那么fragment会被停止, 如果用户导航回来,它将会被恢复.
如果添加多个fragment到同一个容器,那么添加的顺序决定了它们在view hierachy中显示的顺序.对于每一个fragment事务, 如果需要添加一个事务动画, 可以通过在提交事务之前调用setTransition()实现.
实际上,调用 commit() 并不立即执行事务.恰恰相反, 它将事务安排排期, 一旦准备好, 就在activity的UI线程上运行(主线程).如果有必要, 可以在UI线程中调用 executePendingTransactions() 来立即执行由commit()提交的事务. 但这么做通常不必要, 除非事务是其他线程中的job的一个从属.
只能在activity保存它的状态(当用户离开activity)之前使用commit()提交事务.如果试图在那个点之后提交, 会抛出一个异常.这是因为如果activity需要被恢复, 提交之后的状态可能会丢失.对于觉得可以丢失提交的状况, 使用 commitAllowingStateLoss().
四、Fragment之间的通信
Fragment之间通信,我分为两种情况,一是两个Fragment同时在一个activity中,二是两个Fragment不同时存在在前台显示;
(一)、同时显示:对于同时添加显示于activity的情况,比较简单,下面是一个例子
>>.布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:context=".MainActivity" > <fragment
android:id="@+id/fragment1"
android:name="com.fragment.Fragment1"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1" /> <fragment
android:id="@+id/fragment2"
android:name="com.fragment.Fragment2"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1" /> </LinearLayout>
.布局内容
<Button
android:id="@+id/modify"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="修改TextView" /> <!--frag1对应布局内容--> <TextView
android:id="@+id/value"
android:layout_width="match_parent"
android:layout_height="match_parent" /> <!--frag2对应布局内容-->
.Fragment1
public class Fragment1 extends Fragment implements OnClickListener {
/**
* 当fragment被创建的时候调用此方法,返回当前fragment显示的内容
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fig1, null);
Button btn = (Button) v.findViewById(R.id.modify);
btn.setOnClickListener(this);
return v;
}
@Override
public void onClick(View v) {
Fragment2 f2 = (Fragment2) getActivity().getFragmentManager().findFragmentById(R.id.fragment2);
f2.setText("测试修改TextView值");
}
}
.Fragment2
public class Fragment2 extends Fragment {
private TextView tv;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fig2, null);
tv = (TextView) v.findViewById(R.id.value);
return v;
}
public void setText(String str) {
tv.setText(str);
}
}
Android Fragment 使用详解的更多相关文章
- Android Fragment用法详解(2)--动态添加Fragment
在上一篇文章<Android Fragment用法详解(1)--静态使用Fragment>我们讲解了Fragment的最简单的用法.这次我们来说一说Fragment复杂一丢丢的用法.在代码 ...
- Android Fragment用法详解(1)--静态使用Fragment
先说明一下,本例子是运行在Android Studio下面的.同样的代码复制粘贴到Eclipse运行却会报错.具体原因我也没有细查.知道的哥们,留言通知下呗. Fragment,也就是碎片,本意是为了 ...
- Android lifecycle 使用详解
版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/gdutxiaoxu/article/det ...
- android:ToolBar详解
android:ToolBar详解(手把手教程) 泡在网上的日子 发表于 2014-11-18 12:49 第 124857 次阅读 ToolBar 42 来源 http://blog.mosil.b ...
- Android之canvas详解
首先说一下canvas类: Class Overview The Canvas class holds the "draw" calls. To draw something, y ...
- 【转】Android Canvas绘图详解(图文)
转自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1212/703.html Android Canvas绘图详解(图文) 泡 ...
- Android 核心分析 之八Android 启动过程详解
Android 启动过程详解 Android从Linux系统启动有4个步骤: (1) init进程启动 (2) Native服务启动 (3) System Server,Android服务启动 (4) ...
- Android GLSurfaceView用法详解(二)
输入如何处理 若是开发一个交互型的应用(如游戏),通常需要子类化 GLSurfaceView,由此可以获取输入事件.下面有个例子: java代码: package eoe.ClearTes ...
- Android编译过程详解(一)
Android编译过程详解(一) 注:本文转载自Android编译过程详解(一):http://www.cnblogs.com/mr-raptor/archive/2012/06/07/2540359 ...
随机推荐
- NB-IOT移植移动onenet基础通信套件之Object_ID,实例ID,资源ID
1. 访问是按照分层的,Object_ID/实例ID/资源ID,对应每一层ID的数据类型,目前是分为3层,一个实例下面可以有多个实例id,对下面的数据结构来说,如果是资源ID的话,类型只能是asBuf ...
- mysql c 获取error_code
#include <stdio.h> #include <mysql.h> int main(int argc, char **argv) { MYSQL *con = mys ...
- 可靠UDP,KCP协议快在哪?
WeTest 导读 云真机已经支持手机端的画面投影.云真机实时操作,对延迟的要求比远程视频对话的要求更高(100ms以内).在无线网络下,如何更实时.更可靠的传输视频流就成了一个挑战.通过websoc ...
- uvaoj 101 - The Blocks Problem(vector应用+技巧)
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=835&page= ...
- Windows如何设置动态和静态ip地址
打开控制面板,一般在电脑的菜单栏能找到,win8和win10可以使用快捷键(win键+X键),找不到的朋友可以搜索一下. 进入到网络和共享中心,点击更改适配器设置. 这里显示的是电脑所以的网络 ...
- NO.01---今天聊聊Vuex的简单入门
作为一款个人认为非常牛x的框架,个人使用起来得心应手,所以近期就记录一下这款框架吧. 首先说一说 Vuex 是什么? 官方给出的解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它 ...
- 【转载】inotify+rsync实时同步 解决同步慢问题 (转载备记)
原文地址:http://www.ttlsa.com/web/let-infotify-rsync-fast/ 背景 我们公司在用inotify+rsync做实时同步,来解决分布式集群文件一致性的问题. ...
- js实现滑动器效果
最近公司在做一个项目,页面中要用到滑动器效果,我的第一反应是使用HTML5 input类型中的range类型,但马上我就否定了这个想法,因为range类型存在浏览器的兼容性问题(在主流浏览器中).但又 ...
- Greedy Gift Givers 贪婪的送礼者
Description 对于一群要互送礼物的朋友,TRW要确定每个人送出的钱比收到的多多少.在这一个问题中,每个人都准备了一些钱来送礼物,而这些钱将会被平均分给那些将收到他的礼物的人.然而,在任何一群 ...
- Alpha发布文案加美工展示
目录 团队简介 项目进展 组内分工 队员总结 后期计划 一.团队简介 二.项目进展 从选题发布到今天的Alpha发布,我们团队经历了许许多多的磨难.我们最终设计了如下的功能:首页.班级.个人.更多.打 ...