片段 - 您是不是必须在包含整个 Activity 的片段周围使用 Activity Wrapper?

Posted

技术标签:

【中文标题】片段 - 您是不是必须在包含整个 Activity 的片段周围使用 Activity Wrapper?【英文标题】:Fragments - Do you have to use an Activity Wrapper around a fragment which comprises the whole Activity?片段 - 您是否必须在包含整个 Activity 的片段周围使用 Activity Wrapper? 【发布时间】:2011-10-04 08:25:05 【问题描述】:

考虑来自developers.android.com的示例应用

这描述了像这样使用片段:

在手机上,您可以在 Activity A 上使用 Fragment 1,在 Activity B 上使用 Fragment 2。 在平板电脑上,您拥有更多空间,因此您在活动 A 中使用 Fragment 1 和 Fragment 2。

太棒了! ...但是...在第一个示例(带有电话的示例)中,您使用包含单个<fragment> 的xml 文件创建了一个活动,仅此而已,在活动中您只在该xml 上调用setContentView()?这似乎有很多冗余代码(用于显示片段的活动、XML 和片段):您可以将Fragment 设置为Activity 还是始终需要带有 XML 的 Wrapper?

【问题讨论】:

【参考方案1】:

啊,找到了here

public class MainMenuHolder extends FragmentActivity 

    @Override
    protected void onCreate(Bundle savedInstanceState) 
    
        super.onCreate(savedInstanceState);
        // If not already added to the Fragment manager add it. If you don't do this a new Fragment will be added every time this method is called (Such as on orientation change)
        if(savedInstanceState == null)
            getSupportFragmentManager().beginTransaction().add(android.R.id.content, new MainMenuFragment()).commit();
    

FragmentActivity 允许您将 Fragment 设置为 android.R.id.content 的内容,我假设它是主干视图的 android 内部 ID。

使用这种方法,你仍然会得到一个大部分冗余的活动(如果你想要的只是片段作为活动)。但是,仍然有一个活动和一个充当容器的 XML 文件的一半。

任何其他答案将不胜感激!

【讨论】:

让您的解决方案向前迈出一步——创建通用SingleFragmentActivity,获取一个片段作为构造函数参数,然后添加它onCreate。然后在每次需要单个片段活动时使用此活动。 @shem - 我做同样的事情 - 我将片段规范名称作为操作传递,因此它可以从字符串中实例化。 好吧,你也可以停止使用 Fragments,除非你真的需要一个。在大多数情况下,使用简单的 Activity 也可以完成这项工作 我创建了一个通用的 SimpleFragmentActivity 来执行此操作(只是嵌入一个片段) - 它还有一个用于实例化的构建器,以便您可以设置标题、主题等。github.com/jt-gilkeson/fragment-utils【参考方案2】:

在线示例并未填写所有空白。我会尽量直接回答你的问题:

“在第一个示例(带有电话的示例)中,您是否应该创建一个带有 xml 文件的 Activity,其中包含单个和一个仅在该 xml 上调用 setContentView() 的 Activity,仅此而已?”

您已经从正确的地方开始。但不仅如此。在 Android 中解决问题的方法总是不止一种,但推荐的方法是根据可用性生成具有动态片段数量的效果。房地产是:

    在 /layout 中为主要(默认)目标方向/device/form-factor/SDK 创建布局 XML 文件 为其他目标设备的最小宽度基线创建布局 XML 文件。您可能还想定位其他方向、SDK 等。 每个布局 XML 文件都有自己定义的片段集 在 Activity 中,检查存在哪些片段。

显然,程序化布局可以采用类似的策略。

在原始问题(来自 Google 的文档)中的示例中,您可以:

layout/main.xml :: 这个布局只有 Fragment 1 layout-sw600dp/main.xml :: 此布局将包含 Fragments 1、2

然后在 MainActivity.java 中检查每个片段是否存在。为此,您可以使用 FragmentManager#findFragmentById() 进行检查,例如:如果 findFragmentById() 为 Fragment-2 返回 null 则 MainActivity 知道设备已加载 layout/main.xml 并且仅支持一个片段。

从示例中“后退”在某种程度上揭示了:在使用 Fragments 之前,您可能已经使用 startAcitityForResult(int) 从 Activity A 调用了 Activity B。在片段范例中,您可能只需要片段 2 的结果导致片段 1 中发生某些事情,因此让 MainActivity 成为看门人是合理的。随着您对示例的扩展,您可能会看到在其他应用程序中,MainActivity 可能需要调用其他活动 - 无论出于何种原因。也许您的目标是具有足够空间容纳 3 个片段的大型平板电脑,但在需要 3 个活动的手机上。事情可能会变得有趣,但 Fragment API 相当强大。

“你可以将 Fragment 设置为 Activity 还是在使用 Fragment 时始终需要 Wrapper?”

片段不是活动。事实上,片段是由活动加载的,所以是的,有人可能会说总是需要一个包装器。您正在触及 Fragments 的另一个微妙方面。尽管 Activity 的行为类似于 MVC 控制器,但 Fragment 可以被称为“迷你控制器”,因为它们的生命周期类似于 Activity 并与 Activity 一起执行。同样,Fragment 的生命周期包含在(“包装”)管理 Fragment 的 Activity 的生命周期内。我建议熟悉 http://developer.android.com/guide/topics/fundamentals/fragments.html#Lifecycle 中记录的 Fragment 生命周期。

【讨论】:

我不知道你在这里回答什么......?【参考方案3】:

更一般地,您可以创建一个片段容器类:

public class SingleFragmentActivity extends Activity 

    public static final String FRAGMENT_NAME = "fragmentName";
    public static final String FRAGMENT_ARGUMENTS = "fragmentArguments";

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        String fragmentName = getIntent().getStringExtra(FRAGMENT_NAME);
        Fragment fragment = Fragment.instantiate(this, fragmentName);
        Bundle fragmentArguments = getIntent().getBundleExtra(FRAGMENT_ARGUMENTS);
        fragment.setArguments(fragmentArguments);
        getSupportFragmentManager().beginTransaction().replace(android.R.id.content,fragment, "tag").commit();
    

现在您可以使用此类将任何片段实例化为独立活动:

public void showFragmentAsActivity() 
    Intent intent = new Intent(this, SingleFragmentActivity.class);
    intent.putExtra(SingleFragmentActivity.FRAGMENT_NAME, MyFragment.class.getName());
    intent.putExtra(SingleFragmentActivity.FRAGMENT_ARGUMENTS,MyFragment.getArgumentsBundle("a string argument"));
    startActivity(intent);

【讨论】:

以上是关于片段 - 您是不是必须在包含整个 Activity 的片段周围使用 Activity Wrapper?的主要内容,如果未能解决你的问题,请参考以下文章

将公共属性和方法公开给 Main Activity 的片段是不是是一种不好的形式?

android - 您是不是必须向清单中添加片段

从片段显示对话框?

片段替换整个屏幕

使用导航架构组件添加(而不是替换)片段

整个应用程序的浮动视图