在Android中使用片段而不是视图有什么好处?


102

为进行开发时Android,您可以将目标(或最低)sdk设置为4(API 1.6),并添加android兼容性软件包(v4)以添加对的支持Fragments。昨天,我这样做了,并成功实现Fragments了可视化来自自定义类的数据。

我的问题是:与Fragments仅从自定义对象获取View并仍支持API 1.5相比,使用它有什么好处?

例如,假设我有Foo.java类:

public class Foo extends Fragment {

    /** Title of the Foo object*/
    private String title;
    /** A description of Foo */
    private String message;

    /** Create a new Foo
     * @param title
     * @param message */
    public Foo(String title, String message) {
        this.title = title;
        this.message = message;
    }//Foo

    /** Retrieves the View to display (supports API 1.5. To use,
     * remove 'extends Fragment' from the class statement, along with
     * the method {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}) 
     * @param context Used for retrieving the inflater */
    public View getView(Context context) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View v = inflater.inflate(R.layout.foo, null);
        TextView t = (TextView) v.findViewById(R.id.title);
        t.setText(this.title);
        TextView m = (TextView) v.findViewById(R.id.message);
        m.setText(this.message);
        return v;
    }//getView 

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        if (container == null) {
            return null;
        }
        View v = inflater.inflate(R.layout.foo, null);
        TextView t = (TextView) v.findViewById(R.id.title);
        t.setText(this.title);
        TextView m = (TextView) v.findViewById(R.id.message);
        m.setText(this.message);
        return v;
    }//onCreateView

}//Foo

这两种方法都非常容易创建和使用,例如在List<Foo>要显示的Activity中使用(例如,以编程方式将每个方法添加到ScrollView),因此它们Fragments真的很有用,还是只是过度夸张地简化了获得一个视图,例如通过上面的代码?


2
片段不必具有UI,它们只是可重用的行为。在这种情况下,视图将是多余的。
菲利普·里查特

我已经在另一个问题中回答了这个问题。请参阅stackoverflow.com/a/14912608/909956 T; dr-有时片段使您可以创建比依赖自定义视图实现更多的可重用组件。请参阅链接以了解原因。
努曼萨拉蒂13年

Answers:


172

使用Fragments的主要原因是用于backstack和生命周期功能。否则,自定义视图将更轻巧且更易于实现。

最初,我实际上尝试使用自定义视图构建电话/平板电脑应用程序。一切似乎都可以在手机和平​​板电脑上使用,甚至可以从单个面板切换到拆分面板。我遇到麻烦的地方是后退按钮和生命周期。因为我只是手动更新视图,所以没有什么可跟踪视图及其状态的历史。因此,后退按钮无法按预期工作,并且即使在生命周期事件(例如旋转应用程序)中也很难重新创建最新状态。要解决此问题,我必须将自定义视图包装在片段中,并使用FragmentManager,以便保存并重新创建以前的状态。

回答后,我意识到一年前我曾发布过一个类似的问题: https : //stackoverflow.com/a/11126397/618881


14
很好的答案。我只是想补充一下,片段可以从4.2版本开始嵌套,或者支持库11版
。– kar

2
感谢@Karlo的更新。我认为这在概念上是不可能的,但是他们通过通过getChildFragmentManager()使用私有FragmentManager解决了该问题。哦,它是API 17,而不是11,可通过支持库获得。
亨利

2
我只是再次看着这个问题,我的经历也发生了变化。这是一个可以很好地理解优点和缺点的答案,并且非常有帮助。谢谢!
Phil

2
希望为此答案+1,但是这样做会破坏当前分数。此外,70不是我最喜欢的数字。
Behnam 2014年

1
去年,我还以为Fragments不提供任何额外的普通功能,但是我体验到,在单击活动后,我失去了下载的所有图像,因此不得不添加缓存实现,现在我正在考虑使用碎片可能很容易
Shirish Herwade

27

我想说片段在两种情况下很有用:如果您将某些设备/方向上的视图分开,并在两个活动中显示它们,而在其他设备上将所有内容显示在一个设备中。如果您使用平板电脑,甚至手机处于横向模式,那将是一个用例:例如,您在一个屏幕上显示项目列表和详细信息。在电话或纵向模式下,您只显示一部分。

另一个用例是可重用的视图。因此,如果您有一些在不同活动中可见的视图,并且还执行了某些操作,则可以将此行为放入一个片段中,然后重新使用它。显然,您也可以使用自定义窗口小部件来执行此操作。

我不会看到为每个View使用Fragments的任何理由,我想这只是一个开销。我只在第一个用例中使用它们,我想说这是一种简化。


谢谢,这绝对有帮助。我想我会坚持观点,并创建自己的“后堆栈”以使其可重用。
Phil

3

Android在Android 3.0(API级别11)中引入了片段,主要是为了在大屏幕(例如平板电脑)上支持更多动态和灵活的UI设计。由于平板电脑的屏幕比手机的屏幕大得多,因此有更多的空间来组合和交换UI组件。片段允许进行此类设计,而无需您管理视图层次结构的复杂更改。通过将活动的布局划分为多个片段,您可以在运行时修改活动的外观并将这些更改保存在由活动管理的后台堆栈中。

在这里您可以阅读更多。


我把所有阅读文档,但是我一直在寻找的东西,更好地解释了他们的利益,如片剂或返回堆栈
菲尔·

3
  1. 场景活动拆分屏幕-我们有一个布局和一个活动来处理左右屏幕部分
  2. 场景FragmentActivity我们在主屏幕上有一个布局,在左边有一个布局,在右边有一个布局

如果您有简单的应用程序,则方案1是好的。

如果要具有多个片段和多个FragmentActivity,并且可以将它们中的每一个结合起来,则第二种情况很好。您也可以在片段之间进行交互。

我已分割屏幕Fragmentactivity,我可以使用“ Intent Extras”来调用它,并告诉fragmentActivity要加载哪个片段。片段之所以不错,是因为它们不在清单中,因此您可以制作可重用的片段和FragmentActvity。

但这会使您的项目更大。但是,如果您进行大型项目,则可以节省很多。因为您可以使用相同的片段或相同的片段活动。

而且我认为这个碎片来得太晚了,所以您必须尝试以新的方式思考。也许只是尝试将您的活动转换为FragmentActivity。稍后尝试找到可重用的代码,并从中创建Fragment。

它有用,但我现在不知道如何。但是我有一些想法。

这总是问题。Android小组做了一些思考,没人知道有什么好处。因为我们很难像以前那样学习,所以这里带来了一些新事物。

我认为Google告诉我们很好,但并非出于原因。


0

在Fragment或Activity上使用CustomView时添加一种情况:

当您使用CursorLoader观察某些视图,ListView或TextView并希望在后端的ContentProvider数据更新时更新它们的显示值(最常见的情况是,您有一项服务,该服务通过定期轮询远程数据库/云中的数据来更新本地数据库)


-2

上面所有注释中没有提到的一件大事是,即使您在执行诸如更改设备方向之类的操作时,Android杀死了该活动并重新启动该活动,该碎片仍然保留在内存中。这样做是出于性能方面的考虑,但是如果您希望碎片被破坏只是发现它们是从头到尾重新创建的,也可能导致意外结果。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.