【问题标题】:Android - onAttach(Context) not called for API 23Android - API 23 不调用 onAttach(Context)
【发布时间】:2015-11-11 15:59:06
【问题描述】:

我已将 SDK 更新到最新版本 (API 23),并且不推荐使用片段的 onAttach(Activity) 方法。因此,现在我使用的是onAttach(Context),而不是使用该方法,但是在生命周期中不会调用该方法。 Activity 是 v7 中 AppCompatActivity 的实例,片段是 Fragment 类 (android.app.Fragment) 的实例。

任何想法如何让onAttach 在 API 23 中工作?

解决方案

我找到了一些可以帮助您理解和解决此问题的答案:

  • 正如我之前提到的,我正在使用 support v7 (AppCompatActivity) 中的活动和 android.app 中的片段。

  • 为了显示片段,我在 Activity 上使用 getFragmentManager 方法获取片段管理器,因此片段管理器是来自 android.app 的 FragmentManager 的一个实例 -> 这就是问题所在

  • 如果您在使用 API 23 的设备上运行应用程序(我在 AS 模拟器上运行过),您会看到将调用 onAttach(Context) 方法。 在 FragmentManager 显示片段的过程中,会在特定时刻调用 onAttach(..) 方法。使用 getFragmentManager() 您将获得片段管理器的实例,该实例可用于在该设备上运行的 Android 版本(例如 API 22、23)。如果应用程序在 API ,此类问题的解决方案是使用支持库中的 FragmentManager。

  • 解决方案:

    1. 使用 getSupportFragmentManager() 将强制您使用支持库中的片段。所以第一个解决方案是用支持库中的片段替换所有片段并使用getSupportFragmentManager()。

    2. 我已经实现的解决方案是处理 2 种可能性(1. 应用在 API = 23)。

    简而言之,在我的实现中,我为项目中的所有片段创建了一个基类,并在其中添加了以下代码:

    /*
     * onAttach(Context) is not called on pre API 23 versions of Android and onAttach(Activity) is deprecated
     * Use onAttachToContext instead
     */
    @TargetApi(23)
    @Override
    public final void onAttach(Context context) {
        super.onAttach(context);
        onAttachToContext(context);
    }
    
    /*
     * Deprecated on API 23
     * Use onAttachToContext instead
     */
    @SuppressWarnings("deprecation")
    @Override
    public final void onAttach(Activity activity) {
        super.onAttach(activity);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            onAttachToContext(activity);
        }
    }
    
    /*
     * Called when the fragment attaches to the context
     */
    protected void onAttachToContext(Context context) {
    }
    

    现在我只需在我需要的所有片段上覆盖 onAttachToContext(Context) 方法。

    【问题讨论】:

    • 你的onAttach(Context) 上有@Override 吗?如果没有,请添加它。如果您随后收到编译器错误,抱怨没有 onAttach(Context),请确保您使用的是 appcompat-v7 的 v23。
    • 是的。我在 onAttach(Context) 上有 @Override。 v7 的版本也是 23.0.0。
    • 刚刚测试过。我的活动也扩展了AppCompatActivity。我已经覆盖了onAttach(Activity)onAttach(Context),并且两者都被我调用了。使用 Nexus 5 (MPA44G) 测试,minSdk = 16,targetSdk = 23。
    • 还没有。我已经尝试支持 v4 并且它有效。您可以尝试使用 support v4。
    • @WédneyYuri 根据this answer,在运行 API 级别 23 的设备上调用 onAttach(Context) 和 onAttach(Activity)。因此,您需要进行上述检查以确保您作为 onAttach 的一部分所做的工作不会在运行 API 级别 23 的设备上执行两次。

    标签: android android-appcompat


    【解决方案1】:

    我是这样解决问题的:

    @TargetApi(23)
    @Override public void onAttach(Context context) {
        //This method avoid to call super.onAttach(context) if I'm not using api 23 or more
        //if (Build.VERSION.SDK_INT >= 23) {
            super.onAttach(context);
            onAttachToContext(context);
        //}
    }
    
    /*
     * Deprecated on API 23
     * Use onAttachToContext instead
     */
    @SuppressWarnings("deprecation")
    @Override public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (Build.VERSION.SDK_INT < 23) {
            onAttachToContext(activity);
        }
    }
    
    /*
     * This method will be called from one of the two previous method
     */
    protected void onAttachToContext(Context context) {}
    

    【讨论】:

    • 关于 onAttach(Context).. API
    • onDetach() 也没有被调用。如果要设置this.context = null怎么办?
    • E/AndroidRuntime: FATAL EXCEPTION: main, java.lang.ClassCastException:, at com.fragment.fragment_home_new.onAttachToContext, at com.fragment.fragment_home_new.onAttach, at android.support.v4.app .FragmentManagerImpl.moveToState,在这里我添加了我的错误的一些必要行。请帮我解决这个问题。提前致谢。
    【解决方案2】:

    您应该尝试使用 Fragment 的支持库版本。

    您需要切换到import android.support.v4.app.Fragment; 而不是import android.app.Fragment;。您还需要确保您使用的是getSupportFragmentManager() 而不是getFragmentManager()

    【讨论】:

    • 我认为这是正确的答案。我假设我可以使用内置的 Fragment,因为我的目标是 SDK 版本 18,但是 Fragment API 在各种 SDK 版本之间存在差异。 Support 库 Fragment 跨版本保持一致,因此它调用 onAttach(Activity activity)。
    • 假设您想使用支持库中没有的 PreferenceFragment,并且您希望将其添加为导航抽屉中的片段之一,您切换到支持片段的解决方案将不起作用
    【解决方案3】:

    请在此处发布有关此 BUG 的信息

    在 GOOGLE AOSP 项目主页上打开了问题:

    https://code.google.com/p/android/issues/detail?id=185465

    ps。这不是您寻找解决此问题的方法并找到任何解决方法的工作.. 而是迫使谷歌修复其损坏的 API! 要做到这一点,你需要像我说的那样抱怨。

    相关问题 - 片段中的 getContext():

    https://code.google.com/p/android/issues/detail?id=185848

    【讨论】:

      【解决方案4】:

      我也遇到了同样的问题。 我的 minSdkVersion 为 19,targetSdkVersion 为 23,我在 AppCompatActivity 中使用 fragmentManager。

      onAttach(Activity activity) 被标记为已弃用,但是当我将其替换onAttach(Context context) 时,我遇到了应用程序崩溃。

      因此,我现在两个版本都存在,当我在 API22 上运行我的应用程序时,onAttach(Activity activity) 被触发,即使它被标记为已弃用。

      我没有在 Android Marshmallow 设备上测试过它,但我的理解是它会运行 onAttach(Context context) 版本,忽略另一个。

      更新以考虑@skaar 在以下 cmets 中的观察: 我现在可以在 API23 上进行测试,并且可以确认在平台 23 上运行会导致调用这两种方法(使用 Activity Context)。感谢您的提醒!

      【讨论】:

      • 有人可以确认吗?
      • 这种行为是我所看到的,除了最后一条语句。假设您使用的是 android.app.Fragment 而不是支持库版本。如果您的编译/目标版本是 23,则不推荐使用 Fragment.onAttach(Activity) 方法。但是,如果您的目标平台 both 方法将被调用。
      【解决方案5】:

      在我阅读了您的回答后@David Rauca 我认为第二个可以解决我的问题。 但是当我查看源代码时。我发现实际上,onAttach(Context context) 在 Android M 上什么都不做,只是调用了旧方法。

      作为解决方案:

      @SuppressWarnings("deprecation")
      

      将其添加到旧方法中是最好的解决方案。

      【讨论】:

        【解决方案6】:

        我也遇到了同样的问题。 我做了什么来解决它:

        1. 将 onAttach 回调的参数类型从 Activity 更改为 Context。 由于未知原因,这种修改导致了以下事实: onAttach(Context) 方法在片段生命周期中不再被调用。作为一个 结果,我的应用程序崩溃了,因为 onAttach 中的代码 方法从未执行过。

        2. 将 onAttach 方法中的代码移到 onCreate 中,因为它 仍然被执行。

        通过此修改,应用程序将像以前一样运行。不需要额外的import 语句。

        【讨论】:

          【解决方案7】:
          @Override
          public void onAttach(Context context) {
              if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                  super.onAttach(context);
                  onAttachToContext(context);
              } else {
                  Activity activity = getActivity();
                  super.onAttach(activity);
                  onAttachToContext(activity);
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2016-05-21
            • 2020-09-05
            • 2020-04-20
            • 1970-01-01
            • 2018-01-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-10-02
            相关资源
            最近更新 更多