前言

学习Java和Android将近一年的时间了,期间的成果应该就是独立完成了一个Android客户端,并且保证了其在主线版本的稳定性。期间遇到了很多坑,也跟着师兄学到了很多Android知识。但是人总是要拥抱变化,不能让自己太安逸,虽然有不舍,但是我已经证明了自己的学习能力,下一步就是开始做Rom Porting了。这里总结一下之前项目中用到最多的Fragment。

Fragment简介

Fragment可以理解成Activity中用户界面的一个行为或者一部分,它必须被嵌套在Activity中。但是一个Fragment有它自己独立的xml布局文件,并且具有良好的封装性,因此特殊情况下Fragment可以很容易用Activity来进行替换。

创建Fragment

创建一个Fragment和创建Activity类似,需要实现XML布局文件和Java Class。 XML布局文件和其他布局文件都一样,例如如下所示的布局文件(fragment_layout.xml):
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"     android:layout_height="match_parent"    android:orientation="vertical" >    <TextView        android:id="@+id/textView"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="@string/testview" />    <Button        android:id="@+id/button"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="@string/button" /></LinearLayout>
Java代码中,一般情况下可以根据需要实现Fragment以下几个生命周期方法:
1. onAttach():当Fragment依附于activity时被调用,可以在该方法中获取activity句柄,从而实现Fragment和activity之间的通信。 2. onCreate():对Fragment做初始化。 3. onCreateView():在第一次为Fragment绘制用户界面时系统会调用此方法。 4. onActivityCreated():在宿主Activity onCreate函数执行完成之后被调用,可以在这个方法里进行Fragment自己的widget实例化和业务逻辑处理。 5. onDestoryView():当Fragment开始被销毁时调用。 6. onStart():当Fragment可见时被调用。 还有许多其他用以操纵Fragment生命周期中各个阶段的回调函数,大家可自行Google学习。

Fragment生命周期

每一个Fragment都有自己的一套生命周期回调方法和处理自己的用户输入事件。对应的生命周期如下图所示:

在Activity中加入Fragment

首先,需要确保Acitivity支持Fragment,因此Activity通常需要继承自FragmentActivity。在Activity中添加Fragment通常有两种方法:静态的和动态的。

静态方法

直接在Activity的XML布局文件中加入Fragment,如下所示:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:baselineAligned="false"    android:orientation="horizontal" >    <fragment        android:id="@+id/first"        android:name="com.example.FristFragment"        android:layout_width="0dp"        android:layout_height="match_parent"        android:layout_weight="1" />    <fragment        android:id="@+id/second"        android:name="com.example.SecondFragment"        android:layout_width="0dp"        android:layout_height="match_parent"        android:layout_weight="1" /></LinearLayout>
<fragment>中的android:name 属性指定了布局中实例化的fragment类 当系统创建Activity布局时,它实例化了布局文件中指定的每一个Fragment,并且为它们调用onCreateView()函数,以获取每一个fragment的布局。系统直接在<fragment>元素位置插入fragment返回的view 注意:每个fragment都需要一个唯一的标识,如果重启activity,系统可用来恢复fragment(并且用来捕捉fragment的事务处理,例如移除)。为了Fragment提供ID有三种方法:
  • 用android:id属性提供一个唯一的标识
  • 用android:tag属性提供一个唯一的字符串
  • 如果上述两个属性都没有,系统会使用其容器视图的ID

动态方法

使用FragmentTranscation。可以使用FragmentTranscation的API来对Activity的Fragment进行操作(例如添加,移除,或者替换Fragment)。参考代码如下:
FragmentManager fragmentManager = getFragmentManager()FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();ExampleFragment fragment = new ExampleFragment();fragmentTransaction.add(R.id.fragment_container, fragment);fragmentTransaction.commit();
传入add()函数的第一个参数是Fragment被放置的ViewGroup,它由资源ID(resource ID)指定,第二个参数就是要添加的fragment。一旦通过FragmentTranscation做了更改,都应当使用commit()视变化生效。

Fragments通信

Fragments之间不应该直接进行通信,它们之间的交互应该通过宿主Activity进行。有三种Fragment和Acitivity交互的方法: 1. Activity创建带参数的Fragment。 2. Activity中保持了Fragment的对象句柄,可通过句柄直接调用该Fragment的public方法。 3. Fragment可在onAttach函数中获取定义的listener句柄。

创建带参数的Fragment

在某些特定的情况下,Fragment可能需要特定的参数来进行初始化。由于Fragment必须只有一个无参构造函数,因此可以考虑使用静态的newInstance方法来创建带参数的Fragment。示例代码如下:
import android.os.Bundle;import android.support.v4.app.Fragment;public class TestFragment extends Fragment {public static TestFragment newInstance(int num, String title) {TestFragment fragment = new TestFragment();Bundle args = new Bundle();args.putInt("num", num);args.putString("title", title);fragment.setArguments(args);return fragment;}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);int num = getArguments().getInt("num", 0);String title = getArguments().getString("title", "");}}
你可以在Activity里,简单的加载一个带参数的Fragment:
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();TestFragment fragment = TestFragment.newInstance(5, "fragment title");ft.replace(R.id.placeholder, fragment);ft.commit();

调用Fragment的方法

因为Activity可以获取嵌入的Fragment的句柄,因此可以直接通过Fragment句柄调用该方法。
public class TestFragment extends Fragment {public void doSomething(String param) {// do something in fragment}}
在Activity中,可以直接通过Fragment的对象句柄调用该方法:
public class MainActivity extends FragmentActivity {    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        TestFragment testFragment = new TestFragment();        testFragment.doSomething("some param");    }}

Fragment Listener

如果Fragment需要共享事件给Activity,则需要利用这个方法。Fragment中定义一个接口,并且由Activity来实现这个接口。在onAttach()方法中将实现了这个接口的Activity获得到。 在Fragment中定义接口代码如下:
import android.support.v4.app.Fragment;public class MyListFragment extends Fragment {  // ...  // Define the listener of the interface type  // listener is the activity itself  private OnItemSelectedListener listener;  // Define the events that the fragment will use to communicate  public interface OnItemSelectedListener {    public void onRssItemSelected(String link);  }  // Store the listener (activity) that will have events fired once the fragment is attached  @Override  public void onAttach(Activity activity) {    super.onAttach(activity);      if (activity instanceof OnItemSelectedListener) {        listener = (OnItemSelectedListener) activity;      } else {        throw new ClassCastException(activity.toString()            + " must implement MyListFragment.OnItemSelectedListener");      }  }  // Now we can fire the event when the user selects something in the fragment  public void onSomeClick(View v) {     listener.onRssItemSelected("some link");  }}
在Activity中实现这个接口:
import android.support.v4.app.FragmentActivity;public class RssfeedActivity extends FragmentActivity implements  MyListFragment.OnItemSelectedListener {    DetailFragment fragment;  @Override  protected void onCreate(Bundle savedInstanceState) {      super.onCreate(savedInstanceState);      setContentView(R.layout.activity_rssfeed);      fragment = (DetailFragment) getSupportFragmentManager()            .findFragmentById(R.id.detailFragment);  }  // Now we can define the action to take in the activity when the fragment event fires  @Override  public void onRssItemSelected(String link) {      if (fragment != null && fragment.isInLayout()) {          fragment.setText(link);      }  }}

更多相关文章

  1. Android(安卓)UI 单线程模型的编程原则以及AsyncTask原理
  2. Android(安卓)数据存储 利用SQLiteDatabase实现简单的学生管理
  3. Android(安卓)小项目之--数据存储【Files】(附源码)
  4. 【Android】界面布局之 LinearLayout(线性布局)
  5. Android(安卓)html5和Android之间的交互
  6. android studio导入其他项目工程报错解决方法
  7. 在SQL数据库保存数据
  8. Android(安卓)ListView工作原理完全解析,带你从源码的角度彻底理
  9. [android app][eclipse技巧]如何快速复写(Override)方法

随机推荐

  1. 获取系统联系人及电话
  2. android in practice_Implementing custo
  3. Android(安卓)ArrayListAdapter泛型类
  4. fragment中加载高德地图出现滑动冲突解决
  5. Human Interface Principles
  6. shell 脚本自动发布 APP
  7. 小红点
  8. github上的安卓开源库汇总
  9. android刷新相册
  10. Fixing “Type Password to Decrypt Stor