Android - onAttach(Context) not called for API 23

David Rauca picture David Rauca · Aug 18, 2015 · Viewed 19.7k times · Source

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.

    Answer

    Francesco Florio picture Francesco Florio · Nov 11, 2015

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