Android 中的片段与自定义视图

Fragment vs. Custom View in Android

Fragment 和Custom View 可以实现类似的功能,我知道fragment 比custom view 的复用性更好,还有其他benefits/enhancements 可以使用Fragment 吗?片段应该取代自定义视图,还是只是针对某些特定目的的增强?

例如下面的代码是fragment:

public class TestFragment extends Fragment {

    private TextView tv_name;
    private Button btn_play;
    private Button btn_delete;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.testfragment, container, false);
    }

    @Override
    public void onStart() {
        super.onStart();

        tv_name = (TextView)getView().findViewById(R.id.tv_name);
        btn_play = (Button)getView().findViewById(R.id.btn_play);
        btn_delete = (Button)getView().findViewById(R.id.btn_delete);

    }
}

自定义视图的代码:

public class TestCustomView extends LinearLayout {

    private TextView tv_name;
    private Button btn_play;
    private Button btn_delete;

    public TestCustomView(Context context, AttributeSet attrs){
        super(context, attrs);

        setOrientation(LinearLayout.HORIZONTAL);
        setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));

        tv_name = new TextView(context);
        addView(tv_name);

        btn_play = new Button(context);
        addView(btn_play);

        btn_delete = new Button(context);
        addView(btn_delete);
    }

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.testfragment, container, false);
    }
}

TestFragmentTestCustomView都可以创建由TextViewButtons组成的视图,并使用Framelayout/fragmentcom.packagename.TestCustomView的标签在 activity 的 xml 布局文件中声明,但是使用 Fragment 有什么好处?

片段有自己的生命周期,这可能是障碍也可能是奖励,具体取决于您的需要。

片段获取生命周期方法,如 onResume 或 onSavedInstanceState,可以帮助您处理应用程序中的状态转换。如果您使用自定义视图,则需要自行处理此类事情。

有人反对使用片段,建议阅读https://developer.squareup.com/blog/advocating-against-android-fragments/

片段可以在不同的场景中使用,但最常用的是:

  • 包装视图
  • headless fragment - 即无视图 => 一般而言不是很有用,但可以使用
  • 可保留片段 - 可以是以上任何一种。通过使用 Fragment.setRetainInstance(true) you can bypass Fragment.onDestroy(),即可以在配置更改时保留片段数据,但片段视图结构仍然是 destroyed/recreated
  • 可以添加到 activity 返回堆栈,即轻松返回按钮以前的状态恢复

有些情况下颈部完全疼痛,然后有些情况可以更快地达到效果。

对于一些自定义和更灵活的情况,片段可能会变得混乱并且管理它们会很困难。因此,在某些情况下,直接处理视图可能非常方便并且更有帮助。不过一切以需求为准。

注意 View也有自己的生命周期,可以store/recreate保存实例状态。多做一点工作,但它也有选择。

自定义视图的优点是简单,其主要目的是在屏幕上显示一段数据。他们必须依赖其他组件才能做更多事情。

将片段视为一个功能单元,一种使用一个或多个视图显示具有特定用途的 UI 的一部分的方法。片段连接到 Activity 生命周期,它们可以包含和控制加载器以用数据填充视图。它们还可以包括子片段。最后,它们也可以添加到合成后栈中。他们可以做很多事情,但学习起来有些复杂。

如您所见,Fragments 与 Activity 的共同点比它们与自定义视图的共同点多得多。

附带说明一下,片段也可以是无头的(没有 UI)。无头片段提供了一种封装非可视化功能的方法,它依赖于单独组件中的 Activity 生命周期。

使用 Fragments 而不是 Custom Views 最有用的功能是它们有自己的生命周期回调,即我们可以注册自己的 FragmentLifecycleCallbacks 来执行一些操作 before/after Fragment creation/destruction.

我们可以创建自己的 FragmentLifecycleCallbacks 并将其注册到 Activity 以在 FragmentDagger 中注入依赖项。 在 Custom Views 中注入依赖项也有一些变通方法,但是通过 FragmentLifecycleCallbacks 注入依赖项更加简洁和容易。