android学习之Fragment与Activity的绑定

  1. 云栖社区>
  2. 博客>
  3. 正文

android学习之Fragment与Activity的绑定

一生有你llx 2014-11-27 11:30:26 浏览424
展开阅读全文
最近项目忙完了,老大又不让我做android了,总之快速开发接触的东西会很多,只要能解决问题的都是好方法,但从个人的角度而言,快速的开发让人无法深入了解一些技术,虽然现在在项目中可能不会做android了,但是既然开始学习了就不要放弃,继续自己的学习。

Fragment在android中被称为碎片,该技术的引入主要是解决android开源的多种屏幕适配问题,在平板、手机、电视都在使用android的情况下,单纯的采用activity会导致UI的单一,Fragment为了解决这种问题在android sdk11中引入。fragment需要绑定到activity中才能运行。

Fragment和Activity在某种程度有一定的相似性,也有类似的生命周期。但是Fragment必须依附于Activity,同时Activity不能被替换、删除等操作,而Fragment允许被替换和删除。

Fragment可以通过UI控件fragment绑定对应的Fragment也可以采用动态的添加方式。两种方式,第一种相对比较简单,而第二种则更加的灵活,通常是实际使用中合理的选择其中的一种方式。Fragment的灵活性大于Activity,因此目前android的设计中推崇AUF,就是所有的都使用Fragment。

第一种方式的实现通常在XML的布局文件中显示的定义对应的Fragmet的信息。

点击(此处)折叠或打开

  1. fragment xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:id="@+id/helloFragment"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:name="com.example.hell.HelloFragment">
  6. /fragment>
其中的android就是对应的Fragment的类名,这种方式不能方便的进行扩展和取消。

在最近的学习中,较好的体验了android设计的MCV思想,M通常是指数据相关的模型,也就是设计相关的数据模块,这种将设计的会使得数据是独立于其他组件的,C是指控制模块,这个模块会实现UI显示与数据的关联,实现具体的控制关联,V是指显示功能,将相关的数据信息通过控制显示出来。因此在android的功能设计的过程中最好将相关的数据信息作为单独的类,并提供管理这些数据的单一实例工具类,通过这个工具类,控制相关的组件能够访问到这些数据信息。

这些也是在看了一些代码之后的感想而已。AUF的思想通常使得在创建一个activity的过程中都需创建一个对应的Fragment的对象,对应的activity的layout只是提供简单的Fragment容器。

点击(此处)折叠或打开

  1. ?xml version="1.0" encoding='utf-8'?>
  2. FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:id="@+id/fragmentContainer"
  4.     android:layout_width="match_parent"
  5.     android:layout_height="match_parent"
  6.     />
而关于fragment的布局则是实际需要显示的相关ui布局。

点击(此处)折叠或打开

  1. ?xml version="1.0" encoding="utf-8"?>
  2. LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     android:orientation="vertical" >
  6.     
  7.     TextView
  8.         android:layout_width="match_parent"
  9.         android:layout_height="wrap_content"
  10.         android:text="@string/crime_title_label"
  11.         style="?android:listSeparatorTextViewStyle"
  12.         />
  13.     
  14.     EditText
  15.         android:id="@+id/crime_title"
  16.         android:layout_width="match_parent"
  17.         android:layout_height="wrap_content"
  18.         android:hint="@string/crime_title_hint"
  19.         />
  20.     
  21.     TextView
  22.         android:layout_width="match_parent"
  23.         android:layout_height="wrap_content"
  24.         android:text="@string/crime_details_label"
  25.         style="?android:listSeparatorTextViewStyle"
  26.         />
  27.     
  28.     Button
  29.         android:id="@+id/crime_date"
  30.         android:layout_width="match_parent"
  31.         android:layout_height="wrap_content"
  32.         android:layout_marginLeft="16dp"
  33.         android:layout_marginRight="16dp"
  34.         />
  35.     
  36.     CheckBox
  37.         android:id="@+id/crime_solved"
  38.         android:layout_width="match_parent"
  39.         android:layout_height="wrap_content"
  40.         android:layout_marginLeft="16dp"
  41.         android:layout_marginRight="16dp"
  42.         android:text="@string/crime_solved_label"
  43.         />

  44. /LinearLayout>
这样设计的好处是activity不需要针对特定的ui布局,更像是一个通用的布局,所有的fragment都可以再其中添加。而Fragment则需要实现具体的UI布局,这样也从实现上将activity和具体的UI显示独立开来,实现了Fragment的动态添加和UI切换。因此activity更多的是管理Fragment。

Fragment的绑定实现
在AUF的实现中有一种比较常用的方式就是单Fragment的Activity。也就是只有一个Fragment和Activity进行绑定,因此可以提供一个通用的方法用于实现fragment与activity的绑定关系,也就是实现一个单Fragment绑定的Activity类。这样所有的Fragment需要绑定到一个具体的Activity的过程中只需要创建对应的Fragment对象,关于绑定的操作就有该抽象类完成。在代码中添加Fragment的实现会使用到一个Fragment的管理器FragmentManager,这个管理器的操作有点儿类似数据库的事物处理操作过程。具体的实现过程如下所示:

点击(此处)折叠或打开

  1. public abstract class SingleFragmentActivity extends FragmentActivity {
  2.     protected abstract Fragment createFragment();    
  3.     
  4.     @Override
  5.     protected void onCreate(Bundle arg0) {
  6.         super.onCreate(arg0);
  7.         setContentView(R.layout.activity_fragment);
  8.         /* 获取管理器 */
  9.         FragmentManager fm = getSupportFragmentManager();
  10.         Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);  //R.id.fragmentContainer就是容器
  11.         
  12.         if (fragment == null) {
  13.             /* 在activity中添加对应的Fragment的过程 */
  14.             fragment = createFragment();
  15.             fm.beginTransaction()          //具体的操作类似数据库的事务处理过程
  16.                 .add(R.id.fragmentContainer, fragment)
  17.                 .commit();
  18.         }
  19.     }
  20. }
在具体的实现某一个activity的过程中只需要实现对应的抽象函数Fragment createFragment(),同时所有的activity可以通用同一个布局文件。以上的代码实现了一个Fragment和activity的绑定过程,也就是需要使用FragmentManager进行控制。

点击(此处)折叠或打开

  1. public class CrimeActivity extends SingleFragmentActivity {

  2.     @Override
  3.     protected Fragment createFragment() {
  4.             //实现具体的创建过程
  5.     }
  6. }
这样的对于activity就非常的通用,因此在这种单一fragment的情况下可以采用通用的activity。

关于createFragment的实现方式,其实可以针对不同的activity分别实现代码,但是在实际使用过程中都是采用其中一个activity中的Fragment启动另一个activity的方式,因此可能会传递一些参数,而这些参数时针对activity的,而为了实现AUF的思想,在其实activity的过程中就应该启动对应的Fragment。

有时候Fragment有一些归属于当前对象的参数信息需要保存,当然可以保存到归属的activity中,但是考虑到统一性,通常会考虑添加Fragment的Bundle参数,关于Fragment的Bundle参数有点儿类似Activity的Bundle参数,用于保存一些重要的信息,但是Fragment的Bundle参数需要在添加到Acitvity之前绑定,考虑到Fragment的通用性,可以为每一个创建的Fragment都添加一个对应的Bundle argement。具体如下所示:

点击(此处)折叠或打开

  1. public class CrimeFragment extends Fragment{
  2.    ...  
  3.     /* 这是fragment实现bundle的基本规则,在创建fragment的过程中不要调用构造函数 */
  4.     /* 该函数必须为static方法,不然必须先创建对应的对象才能创建fragmet */
  5.     public static CrimeFragment newInstance(UUID crimeId) {
  6.         Bundle args = new Bundle();    //创建bundle参数对象
  7.         args.putSerializable(EXTRA_CRIME_ID, crimeId);  //填充对应的key-word对
  8.         
  9.         CrimeFragment fragment = new CrimeFragment(); //创建对应的Fragment类
  10.         fragment.setArguments(args);    //邦对对应的bundle参数
  11.         
  12.         return fragment;
  13.     }
  14. ...
  15. }
这样就可以在对应的activity中去实现对应的createfragment方法了,具体实现如下所示:

点击(此处)折叠或打开

  1. public class CrimeActivity extends SingleFragmentActivity {

  2.     @Override
  3.     protected Fragment createFragment() {
  4.         UUID crimeId = (UUID) getIntent()
  5.                 .getSerializableExtra(CrimeFragment.EXTRA_CRIME_ID);
  6.         //该参数来自activity,通过newInstance将参数传递给了Fragment
  7.         return CrimeFragment.newInstance(crimeId);
  8.     }
  9. }
虽然newInstance()的实现方法也可以在Activity的createFragment函数实现中完成,但是考虑到可重用性,将Fragment的绑定关系由Fragment实现更加的通用。

通过这种方式,就可以在其中的一个Activity的Fragment中启动另一个Activity中的Fragment。因此基本的实现过程如下所示.

       SinalFragmentActivity(完成Fragment与Activity的绑定操作)
                   |
                 V
                XXXActivity  (实现具体Fragment的创建操作)
                  |
                 V
             获取activity的参数,然后调用Fragment的绑定Bundle的创建函数
                                       
                                      
          XXXFragment
                | 
                V
          定义静态创建实例方法,该方法中实现bundle和Fragment的绑定关系

因此Activity的类的实现方法如下所示:

点击(此处)折叠或打开

  1. public class CrimeActivity extends SingleFragmentActivity {

  2.     @Override
  3.     protected Fragment createFragment() {
  4.         UUID crimeId = (UUID) getIntent()
  5.                 .getSerializableExtra(CrimeFragment.EXTRA_CRIME_ID);
  6.         //获取activity的参数,并通过newInstance函数将对应的参数与、Fragment进行绑定
  7.         return CrimeFragment.newInstance(crimeId);
  8.     }
  9. }
这种实现方法较好的实现了AUF中单Activity和Fragment的绑定实现,这种绑定实现对于Activity的布局非常通用,定义的抽象类也实现了Fragment和Activity的绑定关系。只需要实现对应Fragment的创建操作,为了进一步的实现,要求Fragment提供一种绑定Bundle的静态方法实现一个对象的创建,并绑定了一个bundle的对象。

这种实现方法主要是为了遵循AUF的实现,其实并不需要实现的这么复杂,但是从可重用性的角度分析,这样的实现方法是非常不错的。

有一些优秀的分析可以去拜读一下。
http://www.cnblogs.com/xinye/archive/2012/08/28/2659712.html
http://blog.csdn.net/guolin_blog/article/details/8881711

参考文献:
Android Programming: The Big Nerd Ranch Guide 第10章


网友评论

登录后评论
0/500
评论
一生有你llx
+ 关注