Android-未针对API 23调用onAttach(Context)


73

我已经将SDK更新到最新版本(API 23),onAttach(Activity)不建议使用分段方法。因此,我现在使用的不是使用该方法,onAttach(Context)而是在生命周期中不调用此方法。该活动是AppCompatActivityv7的实例,而该片段是Fragment(android.app.Fragment)类的实例。

有任何想法如何使onAttachAPI 23正常工作吗?

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

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

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

  • 如果您在具有API 23的设备上运行该应用程序(我已经在AS Emulator上运行了该应用程序),则会看到将调用onAttach(Context)方法。在FragmentManager显示片段的过程中,在特定时刻调用onAttach(..)方法。使用getFragmentManager(),您将获得可在该设备上运行的Android版本的片段管理器实例(例如API 22、23)。如果应用程序在API <23的设备上运行,则onAttach(Context)方法不可用,片段管理器不知道API 23中存在onAttach(Context)方法,因此未调用它对于API <23->,针对此类问题的解决方案是使用支持库中的FragmentManager。

  • 解决方案:

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

    2. 我已经实现的解决方案是处理2种可能性(1.该应用程序在API <23的设备上运行,该应用程序在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)方法。


    1
    你有@Override你的onAttach(Context)?如果没有,请添加它。如果随后出现抱怨没有该错误的编译器错误onAttach(Context),请确保您使用的是v23 appcompat-v7
    CommonsWare

    1
    是。我在onAttach(Context)上有@Override。v7的版本也是23.0.0。
    大卫·劳卡

    1
    刚刚测试。我的活动AppCompatActivity也在扩展。我已经覆盖了onAttach(Activity)onAttach(Context)并且都被我召唤了。使用Nexus 5(MPA44G)测试,minSdk = 16,targetSdk =
    23。– Mygod

    2
    还没。我已经尝试使用支持v4,并且可以使用。您可以尝试使用支持v4。
    大卫·劳卡

    2
    根据此答案@WédneyYuri ,在运行API级别23的设备上会同时调用onAttach(Context)和onAttach(Activity)。因此,您需要进行上述检查以确保未作为onAttach的一部分进行工作运行API级23的设备上进行两次
    詹纳斯Varmarken

    Answers:


    28

    我以这种方式解决了这个问题:

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

    3
    关于onAttach(Context)..对于API <23,不会调用该方法,因此您不需要检查内部版本。
    David Rauca '16

    onDetach()也未调用。如果要设置this.context = null怎么办?
    Honghe.Wu

    E / AndroidRuntime:致命例外:main,java.lang.ClassCastException :,位于com.fragment.fragment_home_new.onAttachToContext,位于com.fragment.fragment_home_new.onAttach,位于android.support.v4.app.FragmentManagerImpl.moveToState,在这里我添加了我的错误的一些必要之处。请帮我解决这个问题。提前致谢。
    MohanRaj S

    18

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

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


    我认为这是正确的答案。我以为我可以使用内置的Fragment,因为我的目标是SDK版本18,但是Fragment API在各个SDK版本之间都有差异。支持库片段在各个版本之间是一致的,因此,它调用onAttach(Activity activity)。
    2016年

    假设您要使用支持库中未提供的PreferenceFragment,并且希望将其添加为导航抽屉中的片段之一,您的切换为支持片段的解决方案将无法工作
    Jayshil Dave


    5

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

    onAttach(Activity activity)为过时,但我遇到了应用程序被标记为崩溃时,我代替onAttach(Context context)

    因此,现在我同时拥有两个版本,并且当我在API22上运行我的应用程序时,即使已标记为已弃用,也会onAttach(Activity activity) 被触发

    我尚未在Android Marshmallow设备上进行过测试,但我的理解是它将运行该onAttach(Context context)版本,而忽略另一个版本。

    更新以考虑到@skaar在以下注释中的观察:我现在可以在API23上进行测试,并可以确认在平台23上运行会导致两种方法(带有ActivityContext)都被调用。感谢您的注意!


    有人可以确认吗?
    Martin Mlostek

    我的行为是我所看到的,除了最后一条语句。假设您使用的是android.app.Fragment而不是支持库版本。如果您的编译/目标版本为23,则不建议使用Fragment.onAttach(Activity)方法。但是,如果目标平台<23,则仍将使用onAttach(Activity),因为它们将没有onAttach(Context)方法。此外,双方如果在设备与平台版本23.运行方法将被称为
    VMAN

    4

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

    解决方案:

    @SuppressWarnings("deprecation")
    

    只需将其添加到旧方法中就是最佳解决方案。


    3

    我遇到了同样的问题。我为解决该问题所做的工作:

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

    2. 由于onAttach方法中的代码仍会执行,因此将其移动到onCreate方法中。

    进行此修改后,该应用将恢复为以前的功能。无需其他import声明。


    1
    @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);
        }
    }
    
    By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
    Licensed under cc by-sa 3.0 with attribution required.