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组件进行分组.模块化管理, ...
 
随机推荐
- Spring_Hibernate
			
Spring与Hiberante整合 通过hibernate的学习,我们知道,hibernate主要在hibernate.cfg.xml配置文件中 接下来我们看一下hibernate的一个配置文件 h ...
 - nested exception is org.hibernate.MappingException解决方案
			
1.可能是因为映射文件( Order.hbm.xm)配置的class路径出错 <hibernate-mapping> <class name="com.web.bean.O ...
 - python 类属性、静态方法与类方法
			
1. 类属性 1.1 定义 在类中方法外通过属性名 = 属性值定义的属性 访问方式: 类名.属性名 对象名.属性名 class Student: cls_id = 102 stu = Student( ...
 - PCL配置即常见问题
			
1 下载 把与VS版本对应PCL的AllInOne包下载下来.要下对安装包,需要了解安装包的命名的含义,以下面的一个AllInOne包的名字为例. PCL-1.8.0-AllInOne-msvc ...
 - 去掉CSS赘余代码,CSS可以更简洁
			
本篇文章适合css新手学习,对于已经掌握了css的朋友们也可以通过本片文章来复习知识. 作者通过实践,认为在有些情况下css的代码是可以更加简洁的,多数情况下是因为新手对于一些具有多属性的元素代码不能 ...
 - 洛谷 P1420 最长连号【最长合法子序列/断则归一】
			
题目描述 输入n个正整数,(1<=n<=10000),要求输出最长的连号的长度.(连号指从小到大连续自然数) 输入输出格式 输入格式: 第一行,一个数n; 第二行,n个正整数,之间用空格隔 ...
 - POJ3614 [USACO07NOV]防晒霜Sunscreen
			
Sunscreen Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9333 Accepted: 3264 Descrip ...
 - phpstorm配置Xdebug进行调试PHP教程_php技巧_脚本之家
			
运行环境: PHPSTORM版本 : 8.0.1 PHP版本 : 5.6.2 xdebug版本:php_xdebug-2.2.5-5.6-vc11-x86_64.dll ps : php版本和xdeb ...
 - COOKIE与SESSION的详解
			
cookie与session的小例子: 包含cookie记住登录名,session防止用户非法登录2个例子: 问我拿吧,这个下载连接挂了 描述 cookie过程描述 网站为了辨别用户身份.进行 ses ...
 - php 如何生成静态页
			
PHP文件名:dome.php <?php $string = 1; ob_start(); @readfile("templets/list.html"); $text = ...