片段中未调用 onAttach()

Posted

技术标签:

【中文标题】片段中未调用 onAttach()【英文标题】:onAttach() not called in Fragment 【发布时间】:2015-12-12 19:13:43 【问题描述】:

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

在 XML 中创建片段:

<fragment
    android:id="@+id/toolbar"
    class="package.MainToolbarFragment"
    android:layout_
    android:layout_
    tools:layout="@layout/fragment_main_toolbar" />

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

可能是什么问题?

当然,我可以从v4.Fragment 扩展所有片段,但我不想要它。这是不好的做法吗? 还有项目 min sdk 14。

【问题讨论】:

我认为你应该访问这里***.com/questions/32083053/…希望它澄清。 【参考方案1】:

它没有被调用,因为这个方法已经被添加到 API 23 中。如果你在使用 API 23 (marshmallow) 的设备上运行你的应用程序,那么onAttach(Context) 将被调用。在所有以前的 Android 版本上,onAttach(Activity) 将被调用。

http://developer.android.com/reference/android/app/Fragment.html#onAttach(android.app.Activity)

支持库片段独立于平台。因此它适用于所有 API 版本。

【讨论】:

知道我是否应该同时实现它们(对于 api 23 设备)?在 API 23 中是否仍在调用 onAttach(Activity)? @sockeqwe 向你致敬。我错误地导入了新的 Fragment 类,看了几个小时却没有注意到。谢谢 @AvivBenShabat 您应该使用此 API 的应用兼容版本并仅实现该方法的 onAttach(Context context) 版本 现在你应该使用androix片段。【参考方案2】:

虽然 Google 希望我们停止使用已弃用的 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 的方法,因为它们都是公开可见的并且 Activity 是比Context(作为子类)更专业,因此将优先。

【讨论】:

使用支持库还不错。您的方法会导致一些奇怪的行为,例如每次都不会调用 onStart()。 @yehe 也许您可以详细说明支持库除了实现这两种方法之外还做了什么?我将其视为一个包含一些主题和新版本闪光的主要 polyfil 修复程序包,以使旧设备焕然一新。我并不是说这很糟糕,只是当我在 Android 上使用框架时,它大多是无关紧要的。 根据我的经验,实现两种方法在许多设备上都不起作用。已在各种 Nexus、三星手机上进行过测试,其中许多手机都无法使用。调试显示 onAttach(Activity activity) 不会每次都被调用。使用支持库,我从未遇到任何奇怪的错误。【参考方案3】:

除了前面提到的 cmets,我认为需要注意的是,如果您尝试使用 onAttach() 从父 Activity 更新 Fragment 中包含的数据,则在收集时可能会遇到问题当片段膨胀时,Activity 内部的变量为 null 或为空。在 Activity 生命周期的某个时刻,您的数据模型可能会发生变化,需要在片段内进行更新。您可能会尝试获取对已经膨胀的片段的引用,但是当您单步执行代码时会发现 onAttach() 永远不会触发,即使使用包含 Context 或 Activity 对象的覆盖也是如此。

如果您尝试为片段创建侦听器并从onAttach() 回调方法初始化侦听器,onAttach() 将不会触发,除非您在将片段添加到 Activity 时提供如下所示的 tag 参数:

// 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);

【讨论】:

以上是关于片段中未调用 onAttach()的主要内容,如果未能解决你的问题,请参考以下文章

Dagger 2:在片段中调用onAttach之前,注入的对象可能仍为null

片段的 onAttach 中的值的可能性是啥

在 onActivityCreated() 之后再次调用 Fragment 的 onAttach()

OnDetach/onAttach 片段重新创建片段活动

片段交互回调:onAttach() vs setter

是否最好使用 Activity.onAttachFragment 或 Fragment.onAttach 在 Activity 和嵌套片段之间进行通信?