Fragment学习(二): 管理Fragment和Fragment通讯
一、 管理Fragment
首先,如果你想在Android3.0及以下版本使用Fragment,你必须引用android-support-v4.jar这个包
然后你写的activity不能再继承自Activity类了,而是要继承android.support.v4.app.FragmentActivity,一些其他的父类也有相应的变化.
此处,我们关系Android3.0以上自带的Fragment的管理,要管理Fragment们,需使用FragmentManager,要获取它,需在Activity中调用方法getFragmentManager()。
你可以用FragmentManager来做以上事情:
1. 使用方法findFragmentById()或findFragmentByTag(),获取activity中已存在的fragment们。
2. 使用方法popBackStack()从activity的后退栈中弹出fragment们(这可以模拟后退键引发的动作)。
3. 用方法addOnBackStackChangedListerner()注册一个侦听器以监视后退栈的变化。
你还可以使用FragmentManager打开一个FragmentTransaction来执行fragment的事务,比如添加或删除Fragment
执行Fragment的事务
在Activity中使用Fragment的一个伟大的好处是能跟据用户的输入对Fragment进行添加、删除、替换以及执行其它动作的能力。你提交的一组Fragment的变化叫做一个事务。事务通过FragmentTransaction来执行。你还可以把每个事务保存在Activity的后退栈中,这样就可以让用户在fragment变化之间导航(跟在activity之间导航一样)。
你可以通过FragmentManager来取得FragmentTransaction的实例,如下:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
一个事务是在同一时刻执行的一组动作(很像数据库中的事务)。你可以用add(),remove(),replace()等方法构成事务,最后使用commit()方法提交事务。
在调用commint()之前,你可以用addToBackStack()把事务添加到一个后退栈中,这个后退栈属于所在的Activity。有了它,就可以在用户按下返回键时,返回到Fragment们执行事务之前的状态。
如下例:演示了如何用一个Fragment代替另一个Fragment,同时在后退栈中保存被代替的Fragment的状态。
//Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction=getFragmentManager().beginTransaction();
//Replace whatever is in the fragment_container view with thisfragment,
//and add the transaction to the backstack
transaction.replace(R.id.fragment_container,newFragment);
transaction.addToBackStack(null);
//Commit the transaction
transaction.commit();
解释:newFragment代替了控件ID为R.id.fragment_container所指向的ViewGroup中所含的任何Fragment。然后调用addToBackStack(),此时被代替的Fragment就被放入后退栈中,于是当用户按下返回键时,事务发生回溯,原先的Fragment又回来了。
如果你向事务添加了多个动作,比如多次调用了add(),remove()等之后又调用了addToBackStack()方法,那么所有的在commit()之前调用的方法都被作为一个事务。当用户按返回键时,所有的动作都被反向执行(事务回溯)。
事务中动作的执行顺序可随意,但要注意以下两点:
1. 你必须最后调用commit()。
2. 如果你添加了多个Fragment,那么它们的显示顺序跟添加顺序一至(后显示的覆盖前面的)。
如果你在执行的事务中有删除Fragment的动作,而且没有调用addToBackStack(),那么当事务提交时,那些被删除的Fragment就被销毁了。反之,那些Fragment就不会被销毁,而是处于停止状态。当用户返回时,它们会被恢复。
密技:对于fragment事务,你可以应用动画。在commit()之前调用setTransition()就行。
但是,调用commit()后,事务并不会马上执行。它会在activity的UI线程(其实就是主线程)中等待直到线程能执行的时候才执行(废话)。如果必要,你可以在UI线程中调用executePendingTransactions()方法来立即执行事务。但一般不需这样做,除非有其它线程在等待事务的执行。
警告:你只能在activity处于可保存状态的状态时,比如running中,onPause()方法和onStop()方法中提交事务,否则会引发异常。这是因为fragment的状态会丢失。如果要在可能丢失状态的情况下提交事务,请使用commitAllowingStateLoss()。
二、 Fragment与Activity通讯
与Activity通讯
尽管Fragment的实现是独立于Activity的,可以被用于多个Activity,但是每个Activity所包含的是同一个Fragment的不同的实例。
Fragment可以调用getActivity()方法很容易的得到它所在的activity的对象,然后就可以查找activity中的控件们(findViewById())。例如:
View listView =getActivity().findViewById(R.id.list);同样的,Activity也可以通过FragmentManager的方法查找它所包含的Frament们。例如:
ExampleFragment fragment =(ExampleFragment)getFragmentManager().findFragmentById(R.id.example_fragment);
Activity响应Fragment的事件
有时,你可能需要Fragment与Activity共享事件。一个好办法是在Fragment中定义一个回调接口,然后在Activity中实现之。
例如,还是那个新闻程序的例子,它有一个Activity,Activity中含有两个Fragment。FragmentA显示新闻标题,FragmentB显示标题对应的内容。FragmentA必须在用户选择了某个标题时告诉Activity,然后Activity再告诉FragmentB,FragmentB就显示出对应的内容(为什么这么麻烦?直接FragmentA告诉FragmentB不就行了?也可以啊,但是你的Fragment就减少了可重用的能力。现在我只需把我的事件告诉宿主,由宿主决定如何处置,这样是不是重用性更好呢?)。如下例,OnArticleSelectedListener接口在FragmentA中定义:
public static class FragmentA extends ListFragment{
...
//Container Activity must implement this interface
public interface OnArticleSelectedListener{
public void onArticleSelected(Uri articleUri);
}
...
然后Activity实现接口OnArticleSelectedListener,在方法onArticleSelected()中通知FragmentB。当Fragment添加到Activity中时,会调用Fragment的方法onAttach(),这个方法中适合检查Activity是否实现了OnArticleSelectedListener接口,检查方法就是对传入的activity的实例进行类型转换,如下所示:
public static class FragmentA extends ListFragment{
OnArticleSelectedListener mListener;
...
@Override
public void onAttach(Activity activity){
super.onAttach(activity);
try{
mListener =(OnArticleSelectedListener)activity;
}catch(ClassCastException e){
throw new ClassCastException(activity.toString()+"must implement OnArticleSelectedListener");
}
}
...
如果Activity没有实现那个接口,Fragment抛出ClassCastException异常。如果成功了,mListener成员变量保存OnArticleSelectedListener的实例。于是FragmentA就可以调用mListener的方法来与Activity共享事件。例如,如果FragmentA是一个ListFragment,每次选中列表的一项时,就会调用FragmentA的onListItemClick()方法,在这个方法中调用onArticleSelected()来与activity共享事件,如下:
public static class FragmentA extends ListFragment{
OnArticleSelectedListener mListener;
...
@Override
public void onListItemClick(ListView l,View v,int position,long id){
//Append the clicked item's row ID with the content provider Uri
Uri noteUri =ContentUris.withAppendedId(ArticleColumns.CONTENT_URI,id);
//Send the event and Uri to the host activity
mListener.onArticleSelected(noteUri);
}
...
onListItemClick()传入的参数id是列表的被选中的行ID,另一个Fragment用这个ID来从程序的ContentProvider中取得标题的内容。
Fragment学习(二): 管理Fragment和Fragment通讯的更多相关文章
- Android - Fragment(二)加载Fragment
Fragment加载方法 加载方法有两种,在xml文件中注册,或者是在Java代码中加载. xml中注册 例如在fragment_demo.xml中定义 <?xml version=" ...
- Android学习路线(二十)运用Fragment构建动态UI
要在Android系统上创建一个动态或者多面板的用户界面,你须要将UI组件以及activity行为封装成模块.让它可以在你的activity中灵活地切换显示与隐藏. 你可以使用Fragment类来创建 ...
- ViewPager部分源码分析二:FragmentManager对Fragment状态的管理完成ViewPager的child添加或移出
ViewPager维护child代码流程: 注:PagerAdapter 使用的是FragmentPagerAdapter类或者它的子类. viewPager.populate(): void pop ...
- TabHost选项卡的实现(二):使用Fragment实现
在上一篇博客<TabHost选项卡的实现(一):使用TabActivity实现>中,讲解了如何使用TabActivity创建管理选项卡,但是,通过TabActivity创建选项卡的方式已经 ...
- Android Fragment使用(二) 嵌套Fragments (Nested Fragments) 的使用及常见错误
嵌套Fragment的使用及常见错误 嵌套Fragments (Nested Fragments), 是在Fragment内部又添加Fragment. 使用时, 主要要依靠宿主Fragment的 ge ...
- Android系列之Fragment(二)----Fragment的生命周期和返回栈
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...
- 33.Android之Fragment学习
Fragment Android是在Android 3.0 (API level 11)开始引入Fragment的. 可以把Fragment想成Activity中的模块,这个模块有自己的布局,有自己的 ...
- Android之Fragment学习笔记①
Android Fragment完全解析,关于碎片你所需知道的一切 一. 什么是FragmentFragment(碎片)就是小型的Activity,它是在Android3.0时出现的.Fragment ...
- Android学习笔记(五)Fragment简介
Fragment是在Android 3.0 (API level 11)中引入的Activity的子模块.初衷是为了适应大屏幕的平板电脑,我们只需要使用Fragment对UI组件进行分组.模块化管理, ...
随机推荐
- !important覆写css行内样式
<div class="block"> <span style="font-weight: bold; color: red;">Hel ...
- MSSQL2008 数据压缩方法
数据压缩功能使得SOL Server 2008允许在表.索引和分区中执行数据压缩,这样不仅可以节省磁盘空间,而且允许更多数据置入RAM中,从而提升数据库查询的性能. 1.启用行压缩 如果我们要在指定的 ...
- 利用Eclipse进行远程Debug
这项功能真的十分赞,当我不想写junit test,又想调试在实际环境中才能起作用的Java程序,远程debug真的是太好用了. 参数:java -jar -Xdebug -Xrunjdwp:tran ...
- Python接口自动化(二)接口开发
django 配置开发环境 相关命令 python manage.py runserver 127.0.0.1:8000在指定的地址和端口启动服务 python manage.py startapp ...
- 【python小随笔】单例模式设计(易懂版)
1:单例模式原理 大道理:希望在系统中某个对象只能存在一个,单例模式是最好的解决方案,单例模式是一种常见的软件设置模式,在它的核心结构中只包含一个被称为单例类的特殊类,通过单例模式可以保证系统中的一个 ...
- Django中blank和NULL
当我们在django中添加一个数据库字段时,我们通常会写models.CharField(max_length = 100,null = True,blank = True).用ForeignKey, ...
- BZOJ2802Warehouse Store题解
链接 我太菜了,连贪心题都不会写... 贪心思路很简单,我们能满足顾客就满足他,如果满足不了,就看之前的顾客中 有没有需求比该顾客多的顾客,如果有的话改为卖给这位顾客会使解更优 所以我们用一个优先队列 ...
- 【JZOJ4819】【NOIP2016提高A组模拟10.15】算循环
题目描述 输入 输出 样例输入 167 198 样例输出 906462341 数据范围 解法 令f(n)=∑ni=1i,g(n)=∑ni=1i2 易得ans=∑ni=1∑mj=1f(n−i+1)∗f( ...
- BasicAuth memo
string authInfo = userName + ":" + userPassword; authInfo = Convert.ToBase64String(Encodin ...
- controller接收前台数据—中文乱码问题
项目用的开发环境为tomcat+eclipse+SSM 正如题目,controller接收前台数据-中文乱码问题,在页面编码为UTF-8的前提下,解决方案有二: 一) controller接收数据时, ...