Android - onAttach(Context) not called for API 23

AndroidAndroid Appcompat

Android Problem Overview


I've updated the SDK to the latest version (API 23) and the onAttach(Activity) method for fragment is deprecated. So instead of using that method, now I'm using onAttach(Context) but this one is not called during the lifecycle. The activity is an instance of AppCompatActivity from v7 and the fragment is an instance of class Fragment (android.app.Fragment).

Any ideas how to get the onAttach working in API 23?

Solution

I found some answers that can help you to understand and fix this problem:

  • As I mentioned before I’m using the activity from support v7 (AppCompatActivity) and the fragment from android.app.

  • For showing fragments I get the fragment manager using the method getFragmentManager on the activity, so the fragment manager is an instance of FragmentManager from android.app -> and here is the problem

  • If you run the application on a device with API 23 (I’ve run it on the AS Emulator), you’ll see that the onAttach(Context) method will be called. During the process for showing a fragment by the FragmentManager, at a specific moment the onAttach(..) method is called. Using the getFragmentManager() you’ll get an instance of the fragment manager available for the Android version which is running on that device (for example API 22, 23). In case the application is running on a device with API < 23 the onAttach(Context) method is not available, the fragment manager doesn’t know that in API 23 there is a method onAttach(Context), so that’s why it is not called for the API < 23 -> the solution for this kind of problems is using the FragmentManager from support libraries.

  • Solutions:

    1. Using getSupportFragmentManager() will force you to use a Fragment from the support lib. So the first solution is to replace all fragments with the fragment from support lib and using getSupportFragmentManager().

    2. Solution that I've already implemented is to handle 2 possibilities (1. the app is running on a device with API < 23, the app is running on a device with API >= 23).

    Shortly, in my implementation I have a base class for all fragments from the project and I added this code there:

    /*
     * 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) {
    }
    

    Now I simply override the onAttachToContext(Context) method on all fragments where I need this.

    Android Solutions


    Solution 1 - Android

    I solved the problem in this way:

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

    Solution 2 - Android

    You should try using the Support library version of Fragment.

    You need to switch to import android.support.v4.app.Fragment; instead of import android.app.Fragment;. You'll also need to make sure you're using getSupportFragmentManager() instead of getFragmentManager().

    Solution 3 - Android

    pleas post about this BUG here

    ISSUE OPPENED ON GOOGLE AOSP PROJECT HOMESITE:

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

    ps. this is not your job to search for solution to this problem & to find any kind of workarounds .. but to force google to fix its broken API! to do this u need to complain as i said.

    related issue - getContext() from fragment:

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

    Solution 4 - Android

    I came up with the same issue. I have a minSdkVersion of 19 and a targetSdkVersion of 23 and I am using fragmentManager in an AppCompatActivity.

    onAttach(Activity activity) is marked as deprecated but I ran into app crashes when I replaced it with onAttach(Context context).

    So instead, I now have both versions present and when I run my app on API22, onAttach(Activity activity) is fired, even though it is marked as deprecated.

    I have not tested it on an Android Marshmallow device, but my understanding is that it would run the onAttach(Context context) version, ignoring the other one.

    Update to take into account @skaar's observation in the comments below: I could now test on API23 and can confirm that running on platform 23 causes both methods (with Activity and Context) to be called. Thanks for the heads up!

    Solution 5 - Android

    After I read your answer @David Rauca I think the second one can solve my problem. But when I look into the source code. I found that actually, onAttach(Context context) do nothing on Android M, just called the old method.

    As a solution:

    @SuppressWarnings("deprecation")
    

    Just add it into the old method is the best solution.

    Solution 6 - Android

    I have encountered the same problem. What I have done to resolve it:

    1. Change the argument type of onAttach callback from Activity to Context. For unknown reason, this modification results in the fact that the method onAttach(Context) is not called anymore during the fragment lifecycle. As a consequence, my app was crashing since the code that was in onAttach method has never been executed.

    2. Move the code that was in onAttach method to onCreate one since it gets still executed.

    With this modification, the app turns to functionate as before. No additional import statements were required.

    Solution 7 - Android

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

    Attributions

    All content for this solution is sourced from the original question on Stackoverflow.

    The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

    Content TypeOriginal AuthorOriginal Content on Stackoverflow
    QuestionDavid RaucaView Question on Stackoverflow
    Solution 1 - AndroidFrancesco FlorioView Answer on Stackoverflow
    Solution 2 - AndroidJellibus BellibeanView Answer on Stackoverflow
    Solution 3 - Androidceph3usView Answer on Stackoverflow
    Solution 4 - Android0x4e84View Answer on Stackoverflow
    Solution 5 - AndroidTony ZhangView Answer on Stackoverflow
    Solution 6 - AndroidAndrewView Answer on Stackoverflow
    Solution 7 - AndroidHayk MkrtchyanView Answer on Stackoverflow