当前位置:首页 > 安卓源码 > 技术博客 >

Android Fragment复用的那些事儿

时间:2019-06-06 14:03 来源:互联网 作者:源码搜藏 浏览: 收藏 挑错 推荐 打印

如未特别阐明,本文中的知识点适用于 Activity 重建的时分,即: public void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState) // 略........ if (savedInstanceState != null ) { // 本文评论的状况 } else { // 非本文评论的

 

  • 如未特别阐明,本文中的知识点适用于 Activity 重建的时分,即:

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState) // 略........ if (savedInstanceState != null) { // 本文评论的状况 } else { // 非本文评论的状况 } // 略........ }
    概述
  • 复用的优点:

      一、 为什么要复用Fragment
    • 现在我知道的办法如下:

      FragmentManager.findFragmentByTag(String tag)

      throw new IllegalStateException("Fragment already added: " + fragment)

      ### 理由二:次序不可控 下面的这段代码我信任咱们都很了解,就算自己没有写过也看他人写过

      throw new ClassCastException("Cannot cast android.arch.lifecycle.HolderFragment to MainFragment")

      从 ```ViewModel```相关源码那里能够知道```FragmentManager.getFragments()``` 中包括了其他的Fragment,而这些Fragment的方位往往是不固定,以ViewModel为例,HolderFragment的方位是由初始化的机遇决议的。
      
      
      也便是说你调整了一下 ViewModel 初始化的调用次序或许在Kotlin项目中将 ```lateinit``` 改成了 ```by lazy``` 都或许会发作这样的Crash!就 ```lateinit``` 改成 ```by lazy``` 这条便是我前不久在做项目时实在遇到的。 ### 理由三:26.x.y 版别中行为发作改变 在 版别25 中 Activity 是新建的状况下 回来的是 ```null``` ,在版别26中回来的是 ```Collections.EmptyList[ROOM]()(https://developer.android.google.cn/topic/libraries/architecture/room) 然后有几个界面溃散了! 经过扫除发现而问题就出鄙人面的这段代码中。

      }else{

      mFragments.addAll(fm.getFragments())

      用法示例:

      private MainFragment mainFragment; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) {
              mainFragment = (MainFragment) getSupportFragmentManager() // 这个ID和下面增加 fragment 时指定的 id 要共同 .findFragmentById(android.R.id.content);
          } else {
              mainFragment = new MainFragment();
              getSupportFragmentManager().beginTransaction()
          .add(android.R.id.content, mainFragment)
          .commit();
          }
      }

       

      当一个 ViewGroup 中有多个 Fragment 时 findFragmentById 或许就不是太好使了,这种状况下就需求咱们运用 findFragmentByTag 了。

      办法签名:

      public abstract Fragment findFragmentByTag(String tag);

      上面便是一个很简单的用 TAG 来获取Fragment 的比如,这儿需求留意的便是 tag 参数是咱们在进行 add 或 replace 操作的时分指定的。

       

      上面的 findFragmentById 和 findFragmentByTag 在运用的时分其实都是有一些躲藏约束的:

        所以复用仍是适当有必要的,一起当咱们知道了要复用的根本原因之后,怎么复用Fragment也就变成 【怎么查找已存在的Fragment】的问题了。
        • 依据 TAG 查找 Fragment

        • 【要点】依据 Key 查找 Fragment,这个适宜与 ViewPager 合作

        • 该办法比较适宜 ViewGroup 和 Fragment 是一对一的状况下运用,当不满足该条件时能够运用后边介绍的 findFragmentByTag 办法。

        • 当 一个 ViewGroup 中 有多个 Fragment 时该办法会回来最终增加到该 ViewGroup 的 Fragment。

        • tag 是能够重复的,因为该参数的之仅仅 Fragment 的一个成员变量,仅仅咱们无法拜访(拜访权限 default)。

        • 该办法总是回来 FragmentManager 中和该 tag 共同的最终一个 Fragment。也便是说假如有多个 Fragment 目标运用了同一个 tag 那么最终一个被增加的会被回来,所以不要为不同的 Fragment 目标指定相同的 tag。

        • 不要为同一个 Fragment 实例目标指定在不同的操作中指定不同的 tag,否则会抛出反常,当然这种状况一般是发作在重复增加的状况下

          可是很不巧 ViewPager 与这两个状况都匹配不上,原因:
        • 正确的处理姿态演示:

          private MainFragment mainFragment; private SecondaryFragment secondaryFragment; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) {
                  mainFragment = (MainFragment) fm.getFragment(savedInstanceState, MainFragment.TAG);
                  secondaryFragment = (SecondaryFragment) fm.getFragment(savedInstanceState, SecondaryFragment.TAG);
              } if (mainFragment == null) {
                  mainFragment = new MainFragment();
              } if(secondaryFragment == null){
                  secondaryFragment = new SecondaryFragment()
              } // ViewPager 的相关操作 } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if (mainFragment.isAdded()) {
                  fm.putFragment(outState, MainFragment.TAG, mainFragment);
              } if (secondaryFragment.isAdded()) {
                  fm.putFragment(outState, SecondaryFragment.TAG, secondaryFragment);
              }
          }

          原理解析:

          Android Fragment复用的那些事儿
          上图仅仅给出了咱们现已知道的,不知道的 Fragment 没有表示出来,但不代表不存在

          以 图中 Fragment A 为例,其他的同理

            这次针对 ViewPager 的这种状况我要介绍的办法是 FragmentManager.getFragment()办法,与其配套运用的还有一个 FragmentManager.putFragment()办法。
            • 留意事项:
              • 七、总结

              • Android Fragment复用的那些事儿
                  最终附上一张图告知你怎么挑选适宜的办法来查找Fragment
Android Fragment复用的那些事儿 转载https://www.codesocang.com/appboke/40314.html

技术博客阅读排行

最新文章