在Android Fragment中如何获取getIntent().getExtras()?

108

使用Activities时,我曾这样做:

在Activity 1中:

Intent i = new Intent(getApplicationContext(), MyFragmentActivity.class);
                i.putExtra("name", items.get(arg2));
                i.putExtra("category", Category);
                startActivity(i);

在第二个活动中:

Item = getIntent().getExtras().getString("name");

如何使用Fragments实现这个功能?我同时使用兼容库v4。

这段代码应该放在FragmentActivity中还是放在实际的Fragment中?它应该放在哪个方法中?onCreate?onCreateView?还是其他方法?

能否提供示例代码?

编辑:值得注意的是,我正在尝试将Activity 1保持为Activity(或实际上是ListActivity,当点击列表项时我会传递intent),然后通过一个Fragment Activity传递到一组选项卡式片段,并且我需要任意选项卡都能够获取extras。(我希望这是可能的?)


3
这个问题可能是重复的,但人们似乎更喜欢这个问题。我只是说一下。 - TheLettuceMaster
1
这个问题以前没有被问过。 - andreikashin
2个回答

176

你仍然可以使用

String Item = getIntent().getExtras().getString("name");

fragment中,你只需要先调用getActivity()

String Item = getActivity().getIntent().getExtras().getString("name");

这样可以节省您编写部分代码的时间。


2
一种简单而优雅的检索意图数据的方法。 - zeeshan
8
很难说它简单或优雅,更像是耦合和复杂性。 - Blundell
51
这可能是一个简单的解决方案,但并不是一个好的实践。原因是它会在Fragment和Activity之间创建强烈的依赖关系。主要缺点有1) Fragment变得不可重用(至少在不引入额外约束条件的情况下无法重用于任何使用它的Activity)。2) 它对Fragment的使用产生了一个不明显的软性要求(不清楚使用Fragment是否需要传递给其Activity特定的Intent条目)。请至少了解正确的数据传递方式并做出明智的决定。 - TheIT
将代码从Activity移动到Fragment时,节省时间。 - LK Yeung
8
有时候这种方法是错误的。Fragment 的生命周期并不完全依赖于 Activity 的生命周期,所以在调用 getActivity() 方法时可能会返回 null。只有在 Fragment 的 onCreate 方法和其他一些回调中才是安全的。 - ernazm
显示剩余5条评论

111

我通常会这样做,我相信这也是Google希望开发者这样做的。我会在Activity中获取Intent的额外数据,然后通过为片段实例化参数来传递任何额外数据。

实际上,在Android开发博客上有一个示例,阐述了这个概念,你也会在一些API演示中看到这个概念。虽然这个具体示例是针对API 3.0+ 片段给出的,但使用支持库中的FragmentActivityFragment时,同样适用此流程。

你首先像平常一样在活动中检索意图的额外数据,并将它们作为参数传递给片段:

public static class DetailsActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // (omitted some other stuff)

        if (savedInstanceState == null) {
            // During initial setup, plug in the details fragment.
            DetailsFragment details = new DetailsFragment();
            details.setArguments(getIntent().getExtras());
            getSupportFragmentManager().beginTransaction().add(
                    android.R.id.content, details).commit();
        }
    }
}

不要直接调用构造函数,使用一个静态方法将参数插入片段中可能更容易。在Google给出的示例中,这样的方法通常被称为newInstance。实际上,在DetailsFragment中有一个newInstance方法,因此我不确定为什么上面的代码片段没有使用它...

无论如何,创建片段时提供的所有额外信息都可以通过调用getArguments()来获取。由于它返回一个Bundle,所以其使用方式类似于Activity中的extras。

public static class DetailsFragment extends Fragment {
    /**
     * Create a new instance of DetailsFragment, initialized to
     * show the text at 'index'.
     */
    public static DetailsFragment newInstance(int index) {
        DetailsFragment f = new DetailsFragment();

        // Supply index input as an argument.
        Bundle args = new Bundle();
        args.putInt("index", index);
        f.setArguments(args);

        return f;
    }

    public int getShownIndex() {
        return getArguments().getInt("index", 0);
    }

    // (other stuff omitted)

}

1
如果TextView是片段UI的一部分,那么活动与此无关。将意图额外项作为参数传递到片段的整个原因是您可以在后者内部使用它们,对吧?我建议查看一些在线文档和API示例(可通过Android SDK Manager下载)。 - MH.
2
当您在XML中指定片段而不是使用事务管理器时,是否有一种方法可以这样做? - colabug
1
@MH。我不同意在XML中指定片段时更新数据没有意义。在我的情况下,这是一个食谱详细信息屏幕,我已经从一组搜索结果中获得了所需的所有信息,并希望打开详细信息屏幕。每个实例化的屏幕看起来都会有所不同,但会具有相同的视图元素。在XML中定义比在代码中实例化能够提供许多优势,特别是样式、尺寸等方面。 - colabug
1
@colabug:所以你的论点将是食谱数据,或者至少是某种在运行时唯一已知的标识符。因此,我会选择动态实例化片段。然而,一个简单的替代方案是直接使用从活动检索到的“Intent”数据调用您的片段上的公共方法,如果您的应用程序更复杂并处理单个容器中的不同片段,则可以选择使用接口。 - MH.
2
@JimG。是的,因为该平台依赖于非参数化构造函数来动态(重新)创建“Fragment”实例。这里有几个相关的Q&A,其中您可能会发现这个有用阅读。 - MH.
显示剩余11条评论

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