fragment的使用--备忘

来源:互联网 发布:卫生网络直报系统 编辑:程序博客网 时间:2024/05/21 18:37

                                                 

首先要获取一个FragmentTransaction,这是一个提供多事务执行的一个类,用于执行与Fragment相关的事务,一个Transaction可以插入多个事务,即记录并管理多个操作。

f = Fragment.instantiate(this, fragmentName, args);FragmentTransaction transaction = getFragmentManager().beginTransaction();
FragmentTransaction是一个抽象类,实现它的是BackStackRecord。


* add(...)

/**     * Add a fragment to the activity state.  This fragment may optionally     * also have its view (if {@link Fragment#onCreateView Fragment.onCreateView}     * returns non-null) inserted into a container view of the activity.     *ity state.  This fragment may optionally     * also have its view (if {@link Fragment#onCreateView Fragment.onCreateView}     * returns non-null) inserted into a container view of the activity.     *     * @param containerViewId Optional identifier of the container this fragment is     * to be placed in.  If 0, it will not be placed in a container.     * @param fragment The fragment to be added.  This fragment must not already     * be added to the activity.     * @param tag Optional tag name for the fragment, to later retrieve the     * fragment with {@link FragmentManager#findFragmentByTag * @param containerViewId Optional identifier of the container this fragment is * to be placed in. If 0, it will not be placed in a container. * @param fragment The fragment to be added. This fragment must not already * be added to the activity. * @param tag Optional tag name for the fragment, to later retrieve the * fragment with {@link FragmentManager#findFragmentByTag(String) * FragmentManager.findFragmentByTag(String)}. * * @return Returns the same FragmentTransaction instance. */ public abstract FragmentTransaction add(@IdRes int containerViewId, Fragment fragment, String tag);

由上面的注释部分可以知道add()方法是将Fragment对应的view加入containerViewId对应的ViewGroup中。tag是
用于标识一个fragment的,便于之后查找。add()方法调用后,并不会移除ViewGroup中的去其他Fragment的View,
如果是containerViewId对应的ViewGroup是FragmentLayout的话,那么则会覆盖在之前的Fragment的View上,
若是当前Fragment有些地方是透明的,则会看到下面的东西,所以需要使用FragmentTransaction#show/hide()
去控制Fragment的View在frameLayout中的显示/隐藏。

* add()后,需要去hide所有在该容器(containerViewId)中的fragment,然后在调用show,如下面的代码

if(fragmentA != null)   transaction.hide(fragmentA);//1if(fragmentB != null)   transaction.hide(fragmentB);//2if(fragmentC != null)   transaction.show(fragmentC);//3transaction.addToBackStack("tag");transaction.commit(); 
那么当按返回键时,而还有一个fragmentD在栈顶,D出栈后,就是按顺序实行代码1.2.3去显示fragmentC。


* replace(...l)

/**     * Replace an existing fragment that was added to a container.  This is     * essentially the same as calling {@link #remove(Fragment)} for all     * currently added fragments that were added with the same containerViewId     * and then {@link #add(int, Fragment, String)} with the same arguments     * given here.     *     * @param containerViewId Identifier of the container whose fragment(s) are     * to be replaced.     * @param fragment The new fragment to place in the container.     * @param tag Optional tag name for the fragment, to later retrieve the     * fragment with {@link FragmentManager#findFragmentByTag(String)     * FragmentManager.findFragmentByTag(String)}.     *     * @return Returns the same FragmentTransaction instance.     */    public abstract FragmentTransaction replace(@IdRes int containerViewId, Fragment fragment,            String tag);
由上可知,replace()方法是将之前加入到containerViewId对应ViewGroup中的fragment移除,移除指的是从ViewGroup
中移除fragment对应的View。然后在使用add(),将fragment加入containerViewId对应ViewGroup中,即作为ViewGroup的child。
replace相当于调用了remove()+add(),tag是用于标识一个fragment的,便于之后查找。


* 在onDestroyView()中需要释放关联的View资源,好让fragment占用的大部分内存可以尽快释放。代码如下:

@Override    public void onDestroyView() {        Utils.unbindDrawables(getView());        super.onDestroyView();    }public static void unbindDrawables(View view) {        try {            if (view instanceof ImageView) {                ((ImageView) view).setImageResource(0);                ((ImageView) view).setImageBitmap(null);                ((ImageView) view).setImageDrawable(null);            }            if (view.getBackground() != null) {                view.getBackground().setCallback(null);            }            if (view instanceof ViewGroup && !(view instanceof AdapterView)) {                for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {                    unbindDrawables(((ViewGroup) view).getChildAt(i));                }                ((ViewGroup) view).removeAllViews();            }        } catch (Exception e) {            Log.i(TAG, "unbindDrawables", e);        }    }

Fragment调用detach(),onAttach(),add(),remove(),replace,show(),hide()对fragment生命周期的影响。
http://blog.csdn.net/lvshuchangyin/article/details/52814044

对fragment的使用和一些坑(相信该文章提到的很多坑,Google已经修复了很多)总结得不错的一片文章
http://www.jianshu.com/p/d9143a92ad94

Fragment与Activity的适用性分析


嵌套Fragments

嵌套Fragments Nested Fragments 是Android 4.2 API 17 引入的.
目的: 进一步增强动态复用.
如果要在Android 4.2之前使用, 可以用support library v4的版本, 后面会有详细的迁移过程介绍.
嵌套Fragment的动态添加

在宿主fragment里调用getChildFragmentManager()
即可用它来向这个fragment内部添加fragments.

Fragment videoFragment = new VideoPlayerFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.video_fragment, videoFragment).commit();

同样, 对于内部的fragment来说, getParentFragment() 方法可以获取到fragment的宿主fragment.
getChildFragmentManager() 和 getFragmentManager()

getChildFragmentManager()是fragment中的方法, 返回的是管理当前fragment内部子fragments的manager.
getFragmentManager()在activity和fragment中都有.
在activity中, 如果用的是v4 support库, 方法应该用getSupportFragmentManager(), 返回的是管理activity中fragments的manager.
在fragment中, 还叫getFragmentManager(), 返回的是把自己加进来的那个manager.

也即, 如果fragment在activity中, fragment.getFragmentManager()得到的是activity中管理fragments的那个manager.
如果fragment是嵌套在另一个fragment中, fragment.getFragmentManager()得到的是它的parent的getChildFragmentManager().

总结就是: getFragmentManager()是本级别管理者, getChildFragmentManager()是下一级别管理者.
这实际上是一个树形管理结构.

Android Fragment使用(二) 嵌套Fragments (Nested Fragments) 的使用及常见错误


原创粉丝点击