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中取得标题的内容。

时间: 2024-11-23 01:17:22

Fragment学习(二): 管理Fragment和Fragment通讯的相关文章

fragment 标题-android fragment内部控件跳转fragment 如何替换标题

问题描述 android fragment内部控件跳转fragment 如何替换标题 遇到一个问题 比如 mainActivity 里面有3个fragment,其中一个个人中心fragment里面有多个控件,点击其中一个控件跳转到消息的fragment,但是标题还是显示个人中心 ,要怎么切换标题?代码怎么操作 requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); //声明使用自定义标题 setContentView(R.layout.activit

Fragment 请求网络 切换另一个fragment ! 求大神解答啊 急 !

问题描述 Fragment 请求网络 切换另一个fragment ! 求大神解答啊 急 ! 5C 用RadioGroup 下的三个 RadioButton 管理 , 三个Fragment 是从网络上获取数据显示,网络上获取数据有延迟可能要1秒左右才能显示 ,当数据还没有显示出来时,切换到其他的 fragment 就会报错如下: FATAL EXCEPTION: main java.lang.NullPointerException at android.view.LayoutInflater.f

点击-每次进入一个fragment时,自动刷新该fragment

问题描述 每次进入一个fragment时,自动刷新该fragment 我做了个类似于微博布局的demo.但是运行登陆界面时,fragment就已经加载了.我希望实现的是:fragment,只在点击该fragmeng进去才开始加载数据,不点击就不要加载,同时第二次点击fragment会有刷新功能..希望各位大虾们提供思路. 解决方案 没有图看不到效果,运行登录界面的时候肯定调用了onCreateView方法,点击进去刷新可以在onCreateView方法里面写,但是第二次点击有刷新的功能,其实不太

父Fragment 嵌套多个 Fragment与viewpager中, 子fragment中内容无法显示

问题描述 父Fragment 嵌套多个 Fragment与viewpager中, 子fragment中内容无法显示 如题, FragmentA 里面有个ViewPager ViewPager里是FragB fragc.... Adapter 也使用了getChildFragmentManager() 但是FragmentB/C...的内容不显示 有哪位朋友碰到过这样的问题吗?望指教. 解决方案 可以查查前面的语句吧.

python2-在DJANGO中学习站点管理模块无法使用

问题描述 在DJANGO中学习站点管理模块无法使用 在DJANGO中学习站点管理模块:第一次可以正常登陆(反应很慢),后面就不可以,报如下错误,请我如何解决: Exception happened during processing of request from ('127.0.0.1', 55765) Traceback (most recent call last): File "C:Python27libSocketServer.py", line 295, in handle

android Fragment学习

今天学习了android的Fragment,碎片.碎片是在API11之后才加入到android里面的.有一点很不爽的是,虽说可以动态的增加到activity但是必须在activity的布局文件中有相应的诸如FrameLayout这样的View容器.必须要有ID关联,然后在和Fragment关联. 总结一下Fragment知识: 1 它的出现是为了使得Activity中的组件更加的灵活,可以动态的增加.(其实View本来就可以动态的增加啊,所以,个人认为Fragment其实也是把一组View零件包

Fragment学习(一) :生命周期

一. 何为Fragment Fragment是activity的界面中的一部分或一种行为.你可以把多个Fragment们组合到一个Activity中来创建一个多面界面,并且你可以在多个Activity中重用一个Fragment.你可以把Fragment认为模块化的一段Activity,它具有自己的生命周期,接收它自己的事件,并可以在Activity运行时被添加或删除.Fragment不能独立存在,它必须嵌入到Activity中,而且Fragment的生命周期直接受所在的Activity的影响.例

fragment 二维码-android fragment 集成扫描二维码功能

问题描述 android fragment 集成扫描二维码功能 我在一个activity里放了一个viewpager,viewpager里填充两个fragment, 其中一个fragment是扫描二维码的功能,扫描完以后会跳到另外一个页面,请做过的人提供一点思路,感谢! 解决方案 你用ZXing这个第三方的扫描sdk就可以了 解决方案二: ZXing识别出url,传值给另一个页面,页面中用webview显示. 解决方案三: http://download.csdn.net/detail/zhuo

Android Fragment学习笔记

本程序的重点是在一个Activity中放入了两个Fragment.    页面布局如下面代码(fragment_hide_show.xml): [java] view plaincopy <?xml version="1.0" encoding="utf-8"?>      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"