美文网首页
16_Avtivity 和 Fragment 组合使用的一些问题

16_Avtivity 和 Fragment 组合使用的一些问题

作者: Android_小生 | 来源:发表于2017-08-14 20:17 被阅读76次

1.getActivity() 引用问题

使用中,经常会在 Fragment 中通过 getActivity() 获取到宿主 Activity 对象,但稍有不慎便会引发下面这两个问题:

第一个, Activity 的实例销毁问题。比如,Fragment 中存在类似网络请求之类的异步耗时任务,当该任务执行完毕回调 Fragment 的方法并用到宿主 Activity 对象时,很有可能宿主 Activity 对象已经销毁,从而引发 NullPointException 等异常,甚至造成程序崩溃。

所以,异步回调时需要注意添加空值等判断(譬如:fragment.isAdd()getActivity()!=null 等),或者在 Fragment 创建实例时就通过 getActivity().getApplicationContext() 方法保存整个应用的上下文对象,再来使用;

第二个,内存泄漏问题。如果 Fragment 持有宿主 Activity 的引用,会导致宿主 Activity 无法回收,造成内存泄漏。所以,如果可以的话,尽量不要在 Fragment 中持有宿主 Activity 的引用。

为了解决 Context 上下文引用的问题,Fragment 提供了一个 onAttach(context) 方法,在此方法中我们可以获取到 Context 对象,如下

@Override
    public void onAttach(Context context) {
        super.onAttach(context);
        this.context = context;
    }

2.onActivityResult(int requestCode, int resultCode, Intent intent)

requestCode:请求码(指出该方法是从哪个请求的结果触发的)
resultCode:Activity返回的结果码(指出返回的数据来自于哪个新的Activity)

Fragment 类提供有 startActivityForResult() 方法用于 Activity 间的页面跳转和数据回传,其实内部也是调用 Activity 的对应方法。但是在页面返回时需要注意 Fragment 没有提供 setResult() 方法(设置返回处理结果),可以通过宿主 Activity 实现。

举个例子,在 ActivityA 中的 FragmentA 里面调用 startActivityForResult() 跳转至 ActivityB 中,并在 ActivityB 中的 FragmentB 里面返回到 ActivityA

// FragmentA 中页面跳转和数据回传
...
Intent intent = new Intent(getContext(), ActivityB.class);
getActivity().startActivityForResult(intent, 0);
// FragmentB 里面返回到 ActivityA
Intent intent = new Intent(getActivity(), ActivityA.class);
intent.putExtra("test", test);
getActivity().setResult(0, intent);
getActivity().finish();

在回调时,先会回调 ActivityA 中的 onActivityResult() 方法,然后再分发回调 FragmentA 中的 onActivityResult() 方法。

// 回调 ActivityA 中的 onActivityResult() 方法
   @Override   
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {   
        // 处理特定的结果   
        if (requestCode == 0 && resultCode == 0) {   
            // 取出Intent里的Extras数据   
            Bundle data = intent.getExtras();   
            // 取出Bundle中的数据   
            String result = data.getString("test");   
            Toast.makeText(getApplicationContext(), result, 0).show();   
        }   
    }   
}

...
// 回调 FragmentA 中的 onActivityResult() 方法
...

3.getChildFragmentManager()

Activity:getFragmentManager()

在 Activity 嵌入 Fragment 时,需要使用 FragmentManager,通过 Activity 提供的 getSupportFragmentManager() 方法即可获取,用于管理 Activity 里面嵌入的所有一级 Fragment。

Fragment:getChildFragmentManager()

但是对于继续嵌套二级甚至三级 Fragment,即 Activity 嵌套多级 Fragment。此时在 Fragment 里管理子 Fragment 时,也需要使用到 FragmentManager。但是一定要使用 getChildFragmentManager() 方法获取 FragmentManager 对象。

4.Fragment + ViewPager

ViewPager 提供了两种页面适配器来管理不同 Fragment 之间的滑动切换:FragmentPagerAdapterFragmentStatePagerAdapter

使用 FragmentPagerAdapter 时,ViewPager 中的所有 Fragment 实例常驻内存,当 Fragment 变得不可见时仅仅是视图结构的销毁,即调用了 onDestroyView() 方法。由于 FragmentPagerAdapter 内存消耗较大,所以适合少量静态页面的场景。

使用 FragmentStatePagerAdapter 时,当 Fragment 变得不可见,不仅视图层次销毁,实例也被销毁,即调用了 onDestroyView() 和 onDestroy() 方法,仅仅保存 Fragment 状态。相比而言, FragmentStatePagerAdapter 内存占用较小,所以适合大量动态页面,比如我们常见的新闻列表类应用。

参考文章
Android Fragment 的使用,一些你不可不知的注意事项

相关文章

网友评论

      本文标题:16_Avtivity 和 Fragment 组合使用的一些问题

      本文链接:https://www.haomeiwen.com/subject/mjqprxtx.html