在Android中,Fragment和自定义视图有何区别?

80

Fragment和自定义View可以实现类似的功能,我知道相比自定义View,Fragment更加可重用,使用Fragment有哪些其他好处/增强功能?Fragment是否应该取代自定义View,或仅仅是为了某些特定目的而进行增强?

例如,下面的代码是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);
    }
}

无论是TestFragment还是TestCustomView都可以创建包含TextViewButtons的视图,并使用Framelayout/fragmentcom.packagename.TestCustomView标签在活动的xml布局文件中声明,但是使用Fragment有什么优势呢?


当您需要访问View没有的内容时,例如Fragment生命周期信息或类似“LoaderManager”的内容时,我发现片段非常有用。 - Karakuri
4个回答

42

Fragment可以用于不同的场景,但最常用的包括:

  • 视图包装器
  • 无头片段 - 即没有视图 => 一般情况下没什么帮助,但可以使用
  • 可保留片段 - 可以是以上任何一种。通过Fragment.setRetainInstance(true),您可以绕过Fragment.onDestroy(),即在配置更改时可以保留片段数据,但片段视图结构仍然被销毁/重建
  • 可以添加到活动返回堆栈中,即轻松的后退按钮恢复先前状态

有些情况下,片段会让人感到非常烦恼,但也有些情况下它们可以更快地实现结果。

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

注意 View也有自己的生命周期,并且可以存储/重新创建保存的实例状态。需要做更多的工作,但也有这个选项。


5
谢谢您的回答。能否提供一些具体的例子来说明使用片段与视图的优缺点,以帮助更好地理解哪种方法更适合?目前,我认为片段是最好的选择,但是一些示例可能有助于了解这种方法可能存在的缺点。 - vir us

26

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

将片段视为一个功能单元,一种使用一个或多个视图显示具有特定目的的UI部分的方式。片段与Activity生命周期相连,它们可以包括并控制Loader以用数据填充视图。它们还可以包含子片段。最后,它们也可以添加到综合返回栈中。它们可以做很多事情,学习起来有些复杂。

正如您所看到的,片段与活动(Activity)的共同点比与自定义视图更多。

顺便说一下,片段也可以是无界面(headless)的。无界面片段提供了一种将非可视化功能封装在单独组件中,并依赖于Activity生命周期的方法。


10
明白,但这并没有解释使用片段相比自定义视图的优势是什么。 - Nir Alfasi
3
在问题中给出的例子中,没有任何优势,因为它只是从布局中显示一些静态数据。在实际应用中,当您需要构建依赖于用户交互、加载数据、创建应用程序部分等复杂界面时,您需要同时使用两者。我的观点是,您不能将它们放在同一水平线上进行比较,因为它们有不同的目的。 - BladeCoder

23

Fragment有自己的生命周期,在需要时可能是一种优势或者障碍。

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

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


0
使用Fragments而不是Custom Views最有用的功能是它们具有自己的生命周期回调,即我们可以注册自己的FragmentLifecycleCallbacksFragment创建/销毁之前/之后执行一些操作。
我们可以创建自己的FragmentLifecycleCallbacks并将其注册到Activity中,通过DaggerFragment中注入依赖项。 虽然也有一些解决方案可以在Custom Views中注入依赖项,但通过FragmentLifecycleCallbacks实现会更加清晰和容易。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接