ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

FragmentFactory介绍:构建Fragment的好帮手

2022-01-19 18:01:03  阅读:168  来源: 互联网

标签:好帮手 FragmentFactory Fragment MainFragment fragment instantiate public


1. 为何需要FragmentFactory
关于Fragment的使用约定
有Fragment使用经验的人都知道,Fragment必须有有一个空参的构造函数,否则打包时会提示一下错误:

This fragment should provide a default constructor (a public constructor with no arguments)

在添加了空参构造器之后,如果定义了任何带参数构造器,仍然会亲切的提示:

Avoid non-default constructors in fragments: use a default constructor plus Fragment#setArguments(Bundle) instead [ValidFragment]


因为某些情况下(例如横竖屏旋转等)Fragment会由系统恢复重建,此时系统不知道该选择哪个构造函数,所以系统与开发者约定,统一使用默认的空参构造函数构建,然后通过setArgments设置初始化值。

因此,我们常见的一个做法是通过静态方法,避免定义有参数的构造函数。如下,静态方法getInstance(String str) 中,先空参构造Fragment,然后通过setArgments初始化。

public class MainFragment extends BaseFragment {

   private static final String MY_ARG = "my_arg";
   private String arg = "";

   public static MainFragment getInstance(String str) {
       MainFragment fragment = new MainFragment();
       Bundle bundle = new Bundle();
       bundle.putString(MY_ARG, str);
       fragment.setArguments(bundle);
       return fragment;
   }

   @Override
   public void onCreate(@Nullable Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       if (getArguments() != null) {
           arg = getArguments().getString(MY_ARG);
       }
   }
}

后续便可以使用此静态方法构建Fragment了

MainFragment fragment = MainFragment.getInstance("Hello world!!");

Fragment恢复重建过程中,系统会调用静态方法Fragment.instantiate(在onCreate和onActivityCreated之间)

@NonNull
public static Fragment instantiate(@NonNull Context context, @NonNull String fname,
       @Nullable Bundle args) {
   try {
       Class extends Fragment> clazz = FragmentFactory.loadFragmentClass(
               context.getClassLoader(), fname);
       Fragment f = clazz.getConstructor().newInstance();
       if (args != null) {
           args.setClassLoader(f.getClass().getClassLoader());
           f.setArguments(args);
       }
       return f;
   } catch (java.lang.InstantiationException e) {

我们先前通过setArguments传递的bundle(随着onSaveInstanceState保存),会被系统传递给instantiate,以协助fragment的恢复重建。

AndroidX中新的处理方案
以上这些关于Fragment使用上的约定,随着AndroidX ver. 1.1.0-alpha01的发布成为了历史。

AndroidX中,Fragment.instantiate方法已经被标记位@Deprecated,推荐使用FragmentManager.getFragmentFactory和FragmentFactory.instantiate (ClassLoader, String)作为替代。FragmentFactory作为新的解决方案,取消了以前fragment只能基于空参构造的约定,允许开发者按照需要自由定义其构造函数。


2. 使用方法
假设我们的MainFragment需要两个参数,那么使用FragmentFactory如何构造呢?

定义FragmentFactory
首先,需要定义自己的FragmentFactory。主要是重写instantiate方法,注意跟以前比,已经不支持传入Bundle args作为参数了。即使你想使用bundle传参,也推荐在这里手动setArgument,而非借助系统的设置。

class MyFragmentFactory extends FragmentFactory {

   private final AnyArg anyArg1;
   private final AnyArg anyArg2;

   public MyFragmentFactory(AnyArg arg1, AnyArg arg2) {
       this.anyArg1 = arg1;
       this.anyArg2 = arg2;
   }

   @NonNull
   @Override
   public Fragment instantiate(@NonNull ClassLoader classLoader, @NonNull String className) {
       Class extends Fragment> clazz = loadFragmentClass(classLoader, className);
       if (clazz == MainFragment.class) {
          return new MainFragment(anyArg1, anyArg2);
       } else {
           return super.instantiate(classLoader, className);
       }
   }
}

可见,使用FragmentFactory后,无需静态方法,可以使用构造函数传参即可:

protected MainFragment(AnyArg arg1, AnyArg arg2) {
    this.arg1 = arg1;
    this.arg2 = arg2;
}

设置Factory
接下来需要在合适的时机为FragmentManager设置此Factory

MyFragmentFactory fragmentFactory = new MyFragmentFactory( someObject1,  someObject2);

@Override
public void onCreate(Bundle savedInstanceState) {
    getSupportFragmentManager().setFragmentFactory(fragmentFactory);
    super.onCreate(savedInstanceState);
 
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction()
        .replace(
            R.id.fragment_container,
            MainFragment.class);
    if (addToBackStack) {
           fragmentTransaction.addToBackStack(tag);
    }
    fragmentTransaction.commit();
    
}


fm添加fragment时,会使用factory创建实例。

需要特别注意的是,setFragmentFactory一定要在super.onCreate之前调用,因为在super.onCreate中会进行fragment的重建是需要被使用到。


总结
FragmentFactory的作用很简单:就是帮助开发者自定义并使用带参数的Fragment构造器。这对于dagger、koin等某些DI框架的使用场景中会非常有帮助
 


————————————————
版权声明:本文为CSDN博主「fundroid_方卓」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/vitaviva/article/details/111774009

标签:好帮手,FragmentFactory,Fragment,MainFragment,fragment,instantiate,public
来源: https://blog.csdn.net/chuyouyinghe/article/details/122586580

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有