Android-onAttach(Context)没有为API 23调用

时间:2015-08-18 15:52:00

标签: android android-appcompat

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

如何让onAttach在API 23中运行?

解决方案

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

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

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

  • 如果在具有API 23的设备上运行应用程序(我在AS模拟器上运行它),您将看到将调用onAttach(Context)方法。 在FragmentManager显示片段的过程中,在特定时刻调用onAttach(..)方法。使用getFragmentManager(),您将获得可在该设备上运行的Android版本的片段管理器实例(例如API 22,23)。如果应用程序在API< 23 onAttach(Context)方法不可用,片段管理器不知道在API 23中有一个方法onAttach(Context),因此这就是为什么不调用API< 23 - >解决这类问题的方法是使用支持库中的FragmentManager。

  • 解决方案:

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

    2. 我已经实施的解决方案是处理2种可能性(1.该应用程序在API <23的设备上运行,该应用程序在具有API的设备上运行&gt; = 23)。

    3. 很快,在我的实现中,我有一个来自项目的所有片段的基类,我在那里添加了这些代码:

      /*
       * 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)方法。

    6 个答案:

    答案 0 :(得分:27)

    我用这种方式解决了问题:

    @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) {}
    

    答案 1 :(得分:4)

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

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

    相反,我现在存在两个版本,当我在API22上运行我的应用时,onAttach(Activity activity) 被解雇,即使它被标记为已弃用

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

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

    答案 2 :(得分:4)

    请在这里发布关于此BUG的帖子

    在Google AOSP PROJECT HOMESITE上发布的问题:

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

    PS。寻找这个问题的解决方案并不是你的工作。找到任何类型的解决方法..但强迫谷歌修复其破碎的API! 要做到这一点你需要按照我的说法抱怨。

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

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

    答案 3 :(得分:3)

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

    作为解决方案:

    @SuppressWarnings("deprecation")
    

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

    答案 4 :(得分:2)

    我遇到了同样的问题。 我为解决这个问题做了什么:

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

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

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

    答案 5 :(得分:0)

    @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);
        }
    }