Fragment

来源:互联网 发布:批量重命名软件 编辑:程序博客网 时间:2024/06/07 00:54

Fragment 跟 Activity 之间是如何传值的

当 Fragment 跟 Activity 绑定之后,在 Fragment 中可以直接通过 getActivity()方法获取到其绑定的 Activity 对象, 这样就可以调用 Activity 的方法了。 在 Activity 中可以通过如下方法获取到Fragment 实例

FragmentManager fragmentManager = getFragmentManager();Fragment fragment = fragmentManager.findFragmentByTag(tag);Fragment fragment = fragmentManager.findFragmentById(id);

获取到 Fragment 之后就可以调用 Fragment 的方法。也就实现了通信功能。

描述一下 Fragment 的生命周期

onAttach、onCreate、onCreateView、onActivityCreated、onStart、onResume、onPause、onStop、onDestoryView、onDestroy、onDetach

Fragment 的 replace 和 add 方法的区别

Fragment 本身并没有 replace 和 add 方法, 这里的理解应该为使用 FragmentManager 的 replace和 add 两种方法切换 Fragment 时有什么不同。我们经常使用的一个架构就是通过 RadioGroup 切换 Fragment,每个 Fragment 就是一个功能模块。

case R.id.rb_1:            rb_1.setBackgroundColor(Color.RED);    transaction.show(fragment1);// transaction.replace(R.id.fl, fragment1, "Fragment1");    break;    case R.id.rb_2:            rb_2.setBackgroundColor(Color.YELLOW);// transaction.replace(R.id.fl, fragment2, "Fragment2");    transaction.show(fragment2);    break;    case R.id.rb_3:            rb_3.setBackgroundColor(Color.BLUE);// transaction.replace(R.id.fl, fragment3, "Fragment3");    transaction.show(fragment3);    break;

实现这个功能可以通过 replace 和 add 两种方法。
Fragment 的容器一个 FrameLayout,add 的时候是把所有的 Fragment 一层一层的叠加到了FrameLayout 上了, 而 replace 的话首先将该容器中的其他 Fragment 去除掉然后将当前 Fragment添加到容器中。
一个 Fragment 容器中只能添加一个 Fragment 种类,如果多次添加则会报异常,导致程序终止,而 replace 则无所谓,随便切换。
因为通过 add 的方法添加的 Fragment,每个 Fragment 只能添加一次,因此如果要想达到切换效果需要通过 Fragment 的的 hide 和 show 方法结合者使用。将要显示的 show 出来,将其他 hide起来。这个过程 Fragment 的生命周期没有变化。
通过 replace 切换 Fragment,每次都会执行上一个 Fragment 的 onDestroyView,新 Fragment的 onCreateView、onStart、onResume 方法。
基于以上不同的特点我们在使用的使用一定要结合着生命周期操作我们的视图和数据。

Fragment 如何实现类似 Activity 栈的压栈和出栈效果的?

Fragment 的事物管理器内部维持了一个双向链表结构,该结构可以记录我们每次 add 的Fragment 和 replace 的 Fragment, 然后当我们点击 back 按钮的时候会自动帮我们实现退栈操作。

transaction.addToBackStack("name");    //实现源码 在 BackStackRecord 中    public FragmentTransaction addToBackStack(String name) {        if (!mAllowAddToBackStack) {            throw new IllegalStateException(                    "This FragmentTransaction is not allowed to be added to the back                    stack.");        }        mAddToBackStack = true;        mName = name;        return this;    }

//上面的源码仅仅做了一个标记
除此之外因为我们要使用FragmentManger用的是FragmentActivity, 因此FragmentActivity的 onBackPress 方法必定重新覆写了。打开看一下,发现确实如此。

/**     * Take care of popping the fragment back stack or finishing the activity     * as appropriate.     */    public void onBackPressed() {        if (!mFragments.popBackStackImmediate()) {            finish();        }    }    //mFragments 的原型是 FragmentManagerImpl,看看这个方法都干嘛了    @Override    public boolean popBackStackImmediate() {        checkStateLoss();        executePendingTransactions();        return popBackStackState(mActivity.mHandler, null, -1, 0);    }//看看 popBackStackState 方法都干了啥,其实通过名称也能大概了解 只给几个片段吧,代码太多while(index>=0) {      //从后退栈中取出当前记录对象        BackStackRecord bss = mBackStack.get(index);        if (name != null && name.equals(bss.getName())) {            break;        }        if (id >= 0 && id == bss.mIndex) {            break;        }        index--;    }

Fragment的好处

Fragment 是 android3.0 以后引入的的概念,做局部内容更新更方便,原来为了到达这一点要把多个布局放到一个 activity 里面,现在可以用多 Fragment 来代替,只有在需要的时候才加载Fragment,提高性能。
(1)Fragment 可以使你能够将 activity 分离成多个可重用的组件,每个都有它自己的生命周期和UI。
(2)Fragment 可以轻松得创建动态灵活的 UI 设计,可以适应于不同的屏幕尺寸。从手机到平板电脑。
(3)Fragment 是一个独立的模块,紧紧地与 activity 绑定在一起。可以运行中动态地移除、加入、交换等。
(4)Fragment 提供一个新的方式让你在不同的安卓设备上统一你的 UI。
(5)Fragment 解决 Activity 间的切换不流畅,轻量切换。
(6)Fragment 替代 TabActivity 做导航,性能更好。
(7)Fragment 在 4.2.版本中新增嵌套 fragment 使用方法,能够生成更好的界面效果。

如何切换 fragement,不重新实例化

翻看了 Android 官方 Doc,和一些组件的源代码,发现 replace()这个方法只是在上一个 Fragment不再需要时采用的简便方法.
正确的切换方式是 add(),切换时 hide(),add()另一个 Fragment;再次切换时,只需 hide()当前,show()另一个。
这样就能做到多个 Fragment 切换不重新实例化:

public void switchContent(Fragment from, Fragment to) {    if (mContent != to) {        mContent = to;        FragmentTransaction saction = mFragmentMan.beginTransaction().setCustomAnimations(android.R.anim.fade_in, R.anim.slide_out);        if (!to.isAdded()) { // 先判断是否被 add 过    // 隐藏            saction.hide(from).add(R.id.content_frame, to).commit();            当前的 fragment,add 下一个到 Activity 中        } else {            saction.hide(from).show(to).commit(); // 隐藏当前的            fragment,显示下一个        }    }}
0 0
原创粉丝点击