Fragment中未调用onAttach()方法

64

当从AppCompatActivity启动时,我的Fragment没有调用onAttach(context)方法。

在XML中创建的Fragment:

<fragment
    android:id="@+id/toolbar"
    class="package.MainToolbarFragment"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:layout="@layout/fragment_main_toolbar" />

但是如果我将它从support.v4.Fragment扩展,onAttach(context)会被调用!

可能会出什么问题呢?

当然,我可以将所有片段都从v4.Fragment扩展,但我不想这样做。这是一个不好的做法吗? 此外,项目最小sdk为14。


我认为你应该访问这里:https://dev59.com/k1wY5IYBdhLWcg3w5bTt希望能够澄清。 - Akber
3个回答

131

8
我应该同时实现它们吗(适用于API 23设备)?在API 23中,onAttach(Activity)方法仍然会被调用吗? - Aviv Ben Shabat
@sockeqwe,向您致敬。我错误地导入了新的Fragment类,看了几个小时也没有注意到。谢谢您。 - HenriqueMS
3
你应该使用API的兼容版本,并只实现方法中的onAttach(Context context)部分。 - Nicolás Carrasco-Stevenson
现在你应该使用androix片段。 - Minas Mina

43

尽管谷歌希望我们停止使用已弃用的API

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    ...

它是如此新,以至于它并没有被广泛称为。您还需要实施

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    ...

对我来说它们是相同的,但我喜欢使用KISS原则并且引入另一个支持库会使我的apk翻倍到大约1000kb。我昨天才更新了我的SDK。

这里类型不能互换的原因,在于当提供一个Activity作为参数时,仍将调用接收Activity参数的方法,因为它们都是公开可见的,而ActivityContext更专业化(作为子类),因此将优先考虑使用它。


3
使用支持库并不那么糟糕。你的方法会导致一些奇怪的行为,比如onStart()有时不会被调用。 - yeh
@yehe 或许你可以详细说明一下支持库除了实现这两种方法之外还有什么作用?我认为它主要是一些 polyfil 修复的包,加上一些新版本的主题和闪光效果,以使旧设备焕然一新。我并不是说这样做不好,只是当我在 Android 上使用框架时,它大多数时候都是无关紧要的臃肿。 - John
根据我的经验,实施两种方法在许多设备上并不起作用。已在各种Nexus、三星手机上进行了测试,但在许多设备上都无法正常工作。调试显示onAttach(Activity activity)并非每次都被调用。使用支持库,我从未遇到任何奇怪的错误。 - yeh

0
除了上述的评论之外,我认为需要注意的是,如果您试图使用onAttach()从父Activity更新包含在片段中的数据,当Activity内的集合变量为空或null时,可能会遇到问题。在Activity的生命周期某个时刻,您的数据模型可能会发生更改,并且需要在片段内进行更新。您可能会尝试获取已经填充的片段的引用,但是在代码步进时发现onAttach()从未触发,即使使用包含Context或Activity对象的重写也是如此。
如果您试图为片段创建侦听器并从onAttach()回调方法初始化侦听器,则必须在将片段添加到Activity时提供标记参数,否则onAttach()不会触发,如下所示:
// in the Activity
getFragmentManager().beginTransaction()
    .add(
        R.id.fragmentContainer,
        CustomFragment.newInstance(customDataSource),
        CustomFragment.TAG // Must be passed in for the code below to work
    ).commit();


// Getting a reference to the fragment later on (say to update your data model inside the fragment (in onActivityResult())

CustomFragment fragmentDelegate = (CustomFragment) getFragmentManager().findFragmentByTag(CustomFragment.TAG);
fragmentListener.updateDataSource(customDataSource);

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