Fragment介绍(官方API文档)

[color=red][size=x-large]Fragments[/size][/color]
fragment代表了一种行为或是Activity中UI的一部分。你可以在一个activity中将几个fragment合并成一种组合UI,也可以在多个activity中重复利用同一个fragment。可以认为fragment是activity中的一个组件,它有自己的生命周期,有自己的输入事件,并且可以在activity运行期间添加或移除。
fragment必须存在于一个activity里面并且生命周期受所在的activity的生命周期影响。例如,当一个activity停止的时候,它里面所有的fragment也停止,当activity销毁时,它里面所有的fragment也同时销毁。然而,当一个activity活动时,你可以单独控制它里面的每一个fragment,比如添加或移除。当执行一个fragment事务的时候,你可以把它添加进它所在activity的back栈中——back栈中每一条记录就是一个操作过的fragment事务。这个back栈可以让用户通过按back按钮返回上一次的操作。
当在activity的layout中加入一个fragment,该fragment就存在于该activity视图结构的ViewGroup中而且该fragment也有了自己的视图布局,你可以通过在activity的layout文件中添加标签来插入一个fragment或者通过在已存在的ViewGroup中添加代码。然而,不一定要在activity的layout文件中插入fragment标签,也可以创建一个无UI的fragment在后台为activity工作。

该文档详细介绍了怎样在应用中利用fragment,包括fragment被添加到activity的back栈后是怎么维护它的状态,怎么与activity还有activity中的其他fragment共享事件,怎么创建action bar等等。

设计哲学:
。。。。。

创建Fragment
要创建一个fragment,首先要创建一个继承Fragment的子类(或者是已存在的Fragment子类,比如ListFragment和DialogFragment)。该Fragment子类看起来和activity非常相似,它包括很多和activity类似的回调方法:onCreate(),onStart(),onPause(),onStop()等等。实际上,如果想把一个已存在的android应用转换成利用Fragment,只需要把activity里回调方法的代码分别移动到Fragment对应的的方法中。
通常我们至少需要实现下面生命周期中的方法:
onCreate()
该方法在系统建立fragment时被调用,可以在这里面初始化一些状态,以便从Stop或Pause状态中恢复。

OnCreateView()
当fragment首次绘制自己UI时调用。如果想要绘制自己的fragment UI,你必须在该方法中返回一个View,这个View作为fragment的根视图,如果该fragment不需要提供UI也可以返回null。
OnPause()
用户离开该fragment的时候会调用该方法,和activity的onPause()一样。

几乎所有应用都至少需要实现这三个方法,还有一些fragment生命周期中经常用到的回调方法,在后面的<处理Fragment生命周期>部分会详细介绍。

这里还有一些经常需要继承的fragment子类:
DialogFragment
显示一个悬浮的对话框。利用dialogfragment这个类来创建一个对话框是一种很不错的选择,因为你可以把它压入到所在activity管理的back栈里,可以让用户按back键回退这个对话框。
ListFragment
显示一个由adapter管理的list,跟listActivity类似,它提供了onListItemClick()等几个回调方法来管理该list。
PreferenceFragment
显示一个首选项列表,跟PreferenceActivity类似,这在为应用创建一个“设置”activity的时候很有用。

添加一个用户界面
要为fragment提供视图,首先必须实现onCreateView()回调方法,返回一个View作为根视图。
注意:如果你的fragment是ListFragment的子类,onCreateView()默认返回一个ListView,所以你不需要再重写onCreateView()。
想从onCreateView()中返回一个layout,可以加载定义在XML文件中的资源,onCreateView()提供了一个LayoutInfater对象:
public static class ExampleFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.example_fragment, container, false);
}
}

参数container代表fragment被嵌入的父ViewGroup(可以理解为fragment所在的activity),参数 savedInstanceState和onCreate中的一样,是一个保存着状态的Bundle对象。

在activity中添加一个fragment
有两种把fragment添加到activity的方法:
1.在activity的layout文件中声明fragment
这种情况下,如果是一个view,你可以指定fragment的layout属性。

    android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >

android:name="com.example.news.ArticleListFragment"
android:id="@+id/list"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
android:name="com.example.news.ArticleReaderFragment"
android:id="@+id/viewer"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"/>

android:name属性指定了实现该fragment的类。
当系统创建一个activity布局时,它会通过每一个fragment的onCreateView()方法获取每个fragment的布局,然后分别插入到activity的layout文件标签对应的位置中。

注意:每一个fragment都需要一个唯一的标志好让系统在activity重启的时候去恢复它(你也可以用该唯一标志去获取一个fragment来处理事务,例如移除)。有三种为fragment提供ID的方法:
给属性android:id提供一个唯一的ID
给属性android:tag提供一个唯一的字符串
如果上面两个属性都没有,则系统会用fragment的父容器的ID代替

2.或者,添加一个fragment到一个已有的ViewGroup中
在activity运行的任何时候,你都可以添加一个fragment到activity布局中,你只需要指定一个放置fragment的ViewGroup。
为了执行fragment事务,你需要运用FragmentTransaction。你可以像下面一样从activity中获取一个FragmentTransaction:
FragmentManager fragmentManager = getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
接着你可以用add()方法指定要添加的fragment和要插入到的视图,像这样:
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();

方法add()中第一个参数是fragment需要插入到的ViewGroup,是一个资源ID,第二个参数是需要添加的fragment。
最后,必须加上commint()方法让你的事务起效。
3.添加一个无UI的fragment
上面的例子展示了如何通过添加一个fragment为activity提供UI。然而,你也可以添加一个fragment不提供任何UI只是让它在后台运行。
为了添加一个无UI的fragment, 可以用add(Fragment,String)( 提供一个唯一的字符串“tag”, 而不是一个视图ID)方法。这样添加fragment是因为它与activity的布局并无联系, 不需要调用onCreateView(), 所以你不必实现onCreateView()。
不只是可以给无UI的fragment提供一个字符串tag,也可以为有UI的字符串提供字符串tag,但如果fragment没有UI,一个字符串的tag就是唯一的辨识方法了。如果你需要在稍后重新获得这个fragment,你需要用到方法findFragmentByTag()。
下面这个例子就展示了activity如何用无UI的fragment作为一个后台工作线程。
/** 
* 这个例子展示了当activity因为某些原因(比如配置变化)重启的时候怎么运用Fragment把
* 之前状态传递给activity,这比用API Activity.onRetainNonConfiguratinInstance()
* 简单多了
* This example shows how you can use a Fragment to easily propagate state
* (such as threads) across activity instances when an activity needs to be
* restarted due to, for example, a configuration change. This is a lot
* easier than using the raw Activity.onRetainNonConfiguratinInstance() API.
*/
public class FragmentRetainInstance extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// First time init, create the UI.
if (savedInstanceState == null) {
getFragmentManager().beginTransaction().add(android.R.id.content,
new UiFragment()).commit();
}
}

/**
* This is a fragment showing UI that will be updated from work done
* in the retained fragment.
*/
public static class UiFragment extends Fragment {
RetainedFragment mWorkFragment;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_retain_instance, container, false);

// Watch for button clicks.
Button button = (Button)v.findViewById(R.id.restart);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mWorkFragment.restart();
}
});

return v;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);

FragmentManager fm = getFragmentManager();

// Check to see if we have retained the worker fragment.
mWorkFragment = (RetainedFragment)fm.findFragmentByTag("work");

// If not retained (or first time running), we need to create it.
if (mWorkFragment == null) {
mWorkFragment = new RetainedFragment();
// Tell it who it is working with.
mWorkFragment.setTargetFragment(this, 0);
fm.beginTransaction().add(mWorkFragment, "work").commit();
}
}

}

/**
* This is the Fragment implementation that will be retained across
* activity instances. It represents some ongoing work, here a thread
* we have that sits around incrementing a progress indicator.
*/
public static class RetainedFragment extends Fragment {
ProgressBar mProgressBar;
int mPosition;
boolean mReady = false;
boolean mQuiting = false;

/**
* This is the thread that will do our work. It sits in a loop running
* the progress up until it has reached the top, then stops and waits.
*/
final Thread mThread = new Thread() {
@Override
public void run() {
// We'll figure the real value out later.
int max = 10000;

// This thread runs almost forever.
while (true) {

// Update our shared state with the UI.
synchronized (this) {
// Our thread is stopped if the UI is not ready
// or it has completed its work.
while (!mReady || mPosition >= max) {
if (mQuiting) {
return;
}
try {
wait();
} catch (InterruptedException e) {
}
}

// Now update the progress. Note it is important that
// we touch the progress bar with the lock held, so it
// doesn't disappear on us.
mPosition++;
max = mProgressBar.getMax();
mProgressBar.setProgress(mPosition);
}

// Normally we would be doing some work, but put a kludge
// here to pretend like we are.
synchronized (this) {
try {
wait(50);
} catch (InterruptedException e) {
}
}
}
}
};

/**
* Fragment initialization. We way we want to be retained and
* start our thread.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// Tell the framework to try to keep this fragment around
// during a configuration change.
setRetainInstance(true);

// Start up the worker thread.
mThread.start();
}

/**
* This is called when the Fragment's Activity is ready to go, after
* its content view has been installed; it is called both after
* the initial fragment creation and after the fragment is re-attached
* to a new activity.
*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);

// Retrieve the progress bar from the target's view hierarchy.
mProgressBar = (ProgressBar)getTargetFragment().getView().findViewById(
R.id.progress_horizontal);

// We are ready for our thread to go.
synchronized (mThread) {
mReady = true;
mThread.notify();
}
}

/**
* This is called when the fragment is going away. It is NOT called
* when the fragment is being propagated between activity instances.
*/
@Override
public void onDestroy() {
// Make the thread go away.
synchronized (mThread) {
mReady = false;
mQuiting = true;
mThread.notify();
}

super.onDestroy();
}

/**
* This is called right before the fragment is detached from its
* current activity instance.
*/
@Override
public void onDetach() {
// This fragment is being detached from its activity. We need
// to make sure its thread is not going to touch any activity
// state after returning from this function.
synchronized (mThread) {
mProgressBar = null;
mReady = false;
mThread.notify();
}

super.onDetach();
}

/**
* API for our UI to restart the progress thread.
*/
public void restart() {
synchronized (mThread) {
mPosition = 0;
mThread.notify();
}
}
}
}



管理Fragments
在activity中要管理fragment就要用到FragmentManager,可以在activity中通过方法getFragmentManager()获取。
你可以用Fragmentmanager做如下几件事:
通过findFragmentById()(有UI的Fragment)或者findFragmentByTag()(有和无UI的Fragment)这两个方法取得activity中已有的fragment.
通过popBackStack()从back栈中弹出一个fragment
通过addOnBackStackChangedListener()注册一个监听器监听back栈的变化。

你也可以用FragmentManager打开一个FragmentTransaction来执行Fragment事务,例如添加和移除fragment。

执行Fragment事务
添加,移除,替代或其他一些用户操作是fragment的最好的一个能力体现,每一个你提交到activity的动作都叫做一个事务,可以通过FragmentTransaction来操作。
可以如下从fragmentmanager中获得fragmentTransaction实例:

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

每一个事务都是在同一时间要执行的一组改动。你可以用add(),remove(),replace()这几个方法来发起
改动,然后调用commit()方法把你的改动提交给activity。
在你commit()前,你可能需要调用方法addToBackStack()把事务添加到当前activity管理的back栈中,这可以让用户通过按back按钮返回到之前的fragment状态。
例如,这有个例子用fragment做了替换操作并把该事务保存到back栈中
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();

// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// Commit the transaction
transaction.commit();

在这个例子中,newFragment替换了当前资源ID为R.id.fragment_container的layout中的fragment,而并不需要知道被替换掉的是哪个fragment。通过调用addToBackStack(),替换fragment这一事务操作被保存到了back栈中,这是可以按back按钮来返回的。
注意:如果你在事务中进行了多项操作比如add(),然后remove(),然后replace()再去addToBackStack(),这样的话在你调用commit()前的所有操作
。。。。
。。。
。。

写到一般发现网上有好多类似或一样的,剩下的就不发了。 :?

你可能感兴趣的:(android)