[android](学习笔记1)利用activity托管fragment的基本方法

activity托管fragment,需要做到以下两点:

1. 在布局中为fragment视图安排位置;

2. 管理fragment实例的生命周期。

fragment的生命周期:

参考:http://www.cnblogs.com/purediy/p/3276545.html

fragment在代表activity工作,其生命周期状态反应了activity的生命周期状态。fragment生命周期和activity生命周期的关键区别是:fragment的生命周期方法是由托管activity而不是操作系统调用的。fragment的使用时activity自己内部的事情。



activity作为容器托管内部的fragment,使用代码来灵活添加fragment是一个不错的选择。下面给出一般步骤:

1. 定义activity1的布局文件(文件名activity1.xml),主要用于为即将要添加的fragment1安排位置

activity1.xml: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     />

第3行为该FrameLayout添加id号,方便后续使用。这个FrameLayout就是fragment1的出现位置。注意,这个布局文件不局限于某一个fragment类的对象,它只描述了一个容器的基本信息。

2. 创建UI fragment

创建UI fragment的步骤与创建一个activity的步骤相同:

  • 定义布局文件,组装界面;
  • 创建fragment1类并设置其视图布局为上一步中定义的局部;
  • 使用代码的方式,连接布局文件中生成的组件。

下面详细描述一下每一步的若干细节。

(1) 定义fragment1的布局(fragment1.xml) :

 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     <EditText
13         android:id="@+id/crime_title"
14         android:layout_width="match_parent"
15         android:layout_height="wrap_content"
16         android:layout_marginLeft="16dp"
17         android:layout_marginRight="16dp"
18         android:hint="@string/crime_title_hint"
19         />
20     <TextView
21         android:layout_width="match_parent"
22         android:layout_height="wrap_content"
23         android:text="@string/crime_details_label"
24         style="?android:listSeparatorTextViewStyle"/>
25     <Button
26         android:id="@+id/crime_date"
27         android:layout_width="match_parent"
28         android:layout_height="wrap_content"
29         android:layout_marginLeft="16dp"
30         android:layout_marginRight="16dp"
31         />
32     <CheckBox
33         android:id="@+id/crime_solved"
34         android:layout_width="match_parent"
35         android:layout_height="wrap_content"
36         android:layout_marginLeft="16dp"
37         android:layout_marginRight="16dp"
38         android:text="@string/crime_solved_label"
39         />
40 </LinearLayout>

代码中包含的字符串资源认为已经默认添加到res/values/strings.xml中

(2) 创建fragment1类,并使用fragment1.xml定义的布局:

1 public class fragment1 extends Fragment {
2   @Override
3   public void onCreate(Bundle savedInstanceState) {
4     super.onCreate(savedInstanceState);
5   }
6 }

注意,在fragment1的类定义中,并没有在onCreate方法中生成fragment1的视图。我们将在另一个fragment生命周期方法中完成创建和配置fragment1的视图:

public View onCreateView(LayoutInflater inflater, ViewGroup parent,Bundle savedInstanceState)

利用该方法,将LayoutInflater创建的fragment1的视图对象返回给托管activity1。

定义类fragment1的代码更新为:

 1 public class fragment1 extends Fragment {
 2   @Override
 3   public void onCreate(Bundle savedInstanceState) {
 4     super.onCreate(savedInstanceState);
 5   }
 6
 7   @Override
 8   public View onCreateView(LayoutInflater inflater, ViewGroup parent,Bundle savedInstanceState) {
 9     View v = inflater.inflate(R.layout.fragment1, parent, false);
10   }
11 }

根据fragment的生命周期描述的那样,onCreateView方法是在onCreate调用之后被调用的。注意第9行代码,通过调用LayoutInflater.inflate方法生成的fragment1的视图,传入的是fragment1的布局资源ID。为了自行通过代码添加fragment1的视图给父视图,这里第三个参数选择false。

(3) 使用代码的方式,连接布局文件中生成的组件:

创建的视图对象v中还定义了一系列的控件(参见fragment1.xml的定义),可以通过View.findViewById得到它们。

3. 添加fragment到activity

向托管activity1中添加fragment1,需要使用FragmentManager,它负责具体管理fragment队列和fragment事务的回退栈。

为了得到托管activity1的fragment管理器,可以在它的onCreate方法中添加getFragmentManager方法的调用:

1 public class activity1 extends FragmentActivity {
2   @Override
3   public void onCreate(Bundle savedInstanceState) {
4     super.onCreate(savedInstanceState);
5     setContentView(R.layout.activity1);
6
7     FragmentManager fm = getFragmentManager();// <-- NEW CODE
8   }
9 }

添加fragment1实例到activity1,其实是在向FragmentManager提交一个新的Fragment事务(Add事务),先看代码:

public class activity1 extends FragmentActivity {
    protected abstract Fragment createFragment();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // step1
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity1);

        FragmentManager fm = getFragmentManager();
        // using container view resource to apply a fragment from FragmentManager. <resource ID <--> fragment>
        /*
         *  FragmentManager管理一个fragment队列,容器视图资源可以与一个特定的fragment绑定。
         *  程序试图在当前FragmentManager管理的fragment队列中查找与资源ID(R.id.fragmentContainer)绑定的fragment,
         *  如果找到了就直接返回该fragment,否则就提交一个添加新fragment到队列的事务,提交前绑定新fragment和指定
         *  资源(R.id.fragmentContainer)。这段代码的实际作用,就是保证与R.id.fragmentContainer绑定的fragment存在于
         *  当前FragmentManager管理的fragment队列中。
         *  当添加fragment的事务提交之后,该fragment的生命周期方法onCreate方法和onCreateView方法才依次被调用,
         *  FragmentManager负责调用队列中fragment的生命周期方法。
         */
        Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);

        if (fragment == null) {
            fragment = createFragment();
            // step2
            fm.beginTransaction().add(R.id.fragmentContainer, fragment).commit();
        }
    }
}

代码中已经添加了比较详细的注释,大致意思是先利用资源ID(R.id.fragmentContainer)找与之对应的fragment(想要找到fragment1的实例),如果当前fragment队列中没有匹配的,就提交一个add事务,add一个与资源ID(R.id.fragmentContainer)对应的fragment(fragment1的新实例)。这个资源ID就是一开始提到的fragment1对应的容器(即FrameLayout)的ID。

归纳一下:

activity1的布局对应R.layout.activity1

fragment1的实例对象对应R.id.fragmentcontainer,也从侧面说明,fragment1的实例只是托管activity1的一个组件

fragment1中视图v的布局对应R.layout.fragment1

另外,FragmentManager所管理的fragment队列中有可能已经存在了fragment1的实例(要不然为什么首先通过ID号去find一把),为什么?试想一下,如果activity1因为设备旋转或内存回收而被销毁后再重建,整个过程中,原本存在于activity1中的整个fragment队列都会被保存,自然包括fragment1的实例。activity1在重建时会调用onCreate方法,新的FragmentManager首先获取之前保存的fragment队列,方便地回复之前的状态,fragment1的旧有实例自然已经存在了。

历经三步,fragment1实例成功交由activity1托管(即成功添加到activity1)。

下一篇:主要总结一下界面布局相关的知识。

时间: 2024-11-04 22:14:12

[android](学习笔记1)利用activity托管fragment的基本方法的相关文章

Android学习笔记十四.深入理解fragment(二) 之《图书详情》实战

深入理解fragment(二) 之<图书详情>实战 通过上一篇博文<深入理解fragment一>,我们学习了Android-Fragment的核心知识点.现在在此基础上,利用Fragment技术开发一款适用于大屏幕手机/平板的查找图书详情的应用软件.该项目主要在于两方面,一是Activity.Fragment的源码实现:二是,布局界面资源文件的实现. 1.res/../BookListFragment.java: 自定义类,继承于ListFragment,无需实现OnCreateV

Android学习笔记十五.深入理解fragment(三) 之《兼容多分辨率的应用》实战

深入理解fragment(三) 之<兼容多分辨率的应用>实战 在上一篇博文中介绍了如何使用Android Fragment开发适用于大屏幕应用,现在我们在上一个应用的基础上继续学习如何使用Fragment开发兼容多分辨率的应用. 1.建立/res/values-large/refs.xml引用资源文件 为了开发兼顾屏幕分辨率的应用,我们需要建立一个引用资源文件,专门用于定义各种引用项.refs.xml引用资源文件中定义了一项引用,其作用就是标明activity_book_list实际引用(@)

Android学习笔记四之Activity

Android四大组件之Activity 1.什么是Activity Activity是Android四大组件之一,用于显示View.Activity是一个应用程序组件,提供一个用户交互的接口,其本身是没有界面的,Activity类创建一个窗口,在上面可以绘制用户接口.窗口通常充满屏幕,也可以小于屏幕而悬浮于其他窗口之上. 开发者可以通过Activity类提供的setContentView(View)接口将View放到Activity创建的窗口上.一个程序一般由多个Activity组成,他们通常

Android学习笔记:利用httpclient和AsyncTask 发起网络http post操作

1.在android4中,发起网络http操作,不能在Activity的事件(即主线程)中进行,必须在单独的线程中操作. 另外进行网络操作,需要在manifest文件中增加如下的权限: <uses-permission android:name="android.permission.INTERNET" /> 2.下面给出代码事例 public void loadData() { new AsyncTask<String, Void, String>() { @

Android学习笔记(20)————利用ListView制作带竖线的多彩表格

http://blog.csdn.net/conowen/article/details/7421805 /******************************************************************************************** * author:[email protected]大钟                                                                          

Android学习笔记—第九章 Activity的加载模式

第九章 Activity的加载模式 task:类似于栈,每次打开界面会创建一个task,然后将这开启的界面放入到该task中. (1)standard:默认模式 每次都会创建一个新的界面,将该界面加入task中 (2)singleTop:栈顶单实例模式 a. 如果目标Activity不存在,创建一个新的Activity,存入到task中 b. 如果目标Activity已经存在,并且处于栈顶,不会再创建新的Activity c. 如果目标Activity已经存在,但不处于栈顶,创建一个新的Acti

【转】 Pro Android学习笔记(四二):Fragment(7):切换效果

目录(?)[-] 利用setTransition 利用setCustomAnimations 通过ObjectAnimator自定义动态效果 程序代码的编写 利用fragment transaction进行切换,很方便提供切换的效果. 利用setTransition() 在Pro Android学习笔记(三九):Fragment(4):基础小例子-续的“Step 4:实现showDetail(int index),如何管理fragment”中,介绍了如何在容器FrameLayout中通过frag

android学习笔记——利用BaseAdapter生成40个列表项

RT: main.xml ? 1 2 3 4 5 6 7 8 9 10 11 12 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"               android:orientation="vertical"        

【转】 Pro Android学习笔记(四十):Fragment(5):适应不同屏幕或排版

目录(?)[-] 设置横排和竖排的不同排版风格 改写代码 对于fragment,经常涉及不同屏幕尺寸和不同的排版风格.我们在基础小例子上做一下改动,在横排的时候,仍是现实左右两个fragment,在竖排时,如下图显示: 屏幕上只显示一个fragment,点击列表上的数目,进入到简介的activity.下面介绍实现的方式. 设置横排和竖排的不同排版风格 在 Pro Android学习笔记(四):了解Android资源(下)的“资源和配置的变更”中,我们介绍了如何同资源文件夹名设置不同资源.缺省的l