欢迎来到Doc100.Net免费学习资源知识分享平台!
您的位置:首页 > 程序异常 >

fragment引见(官方api文档)

更新时间: 2014-01-05 02:34:01 责任编辑: Author_N1

 

Fragment介绍(官方API文档)
Fragments
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>来插入一个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属性。
<?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="horizontal" >
    
    <fragment
        android:name="com.example.news.ArticleListFragment"
        android:id="@+id/list"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"/>  
    <FrameLayout
		android:name="com.example.news.ArticleReaderFragment"
        android:id="@+id/viewer"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="2"/>
</LinearLayout>

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

注意:每一个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()前的所有操作
。。。。
。。。
。。

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





上一篇:上一篇
下一篇:下一篇

 

随机推荐程序问答结果

 

 

如对文章有任何疑问请提交到问题反馈,或者您对内容不满意,请您反馈给我们DOC100.NET论坛发贴求解。
DOC100.NET资源网,机器学习分类整理更新日期::2014-01-05 02:34:01
如需转载,请注明文章出处和来源网址:http://www.doc100.net/bugs/t/11521/
本文WWW.DOC100.NET DOC100.NET版权所有。