Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the correct way to deal with the deprecated Fragment events onAttach and onInflate

I have read a few articles and answers (including this one) regarding deprecated code, but I'm a bit confused as to how to handle (specifically) the deprecated Fragment event handler onInflate.

I have replaced my implementation of

public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState)

with

public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState)

If I run my app on a < API23 machine, the replacement code is not called.

If I restore the original deprecated code (so that I now have both methods implemented) then the deprecated code is called, correct functionality returns, but a call is now being made to a deprecated method(?).

And when I run the app on an API23 machine, it appears that BOTH versions of the handler are called.

So the question is, what is happening here? If I am writing code which is supposed to run on both API23 and earlier versions, do I need to implement the deprecated methods as well as the new ones?

And if that's the case, do I need to hunt out and implement other deprecated methods "just in case"? (and, therefore, is there a list of these deprecated methods to "back-code" for?)


UPDATE :

I have now changed from using android.app.Fragment to android.support.v4.app.Fragment (i.e. from native fragments to support fragments) and the app is now performing as expected, with the replacement handler code running for all versions, and is stepping through the android source as expected.

But the question remains : WHY?

Why is the 'native' android.app.Fragment implementation ****ed up? Looking back through earlier questions then this issue was being discussed back in September 2015. So why is it still an issue? And why should there be a difference in the implementation of support and native fragments post API 11?

like image 326
Simon Hutton Avatar asked Mar 21 '16 15:03

Simon Hutton


People also ask

What is onAttach in fragment?

The onAttach() callback is invoked when the fragment has been added to a FragmentManager and is attached to its host activity. At this point, the fragment is active, and the FragmentManager is managing its lifecycle state. At this point, FragmentManager methods such as findFragmentById() return this fragment.

How do you use onAttach?

onAttach() : Called when a Fragment is first attached to a host Activity . Use this method to check if the Activity has implemented the required listener callback for the Fragment (if a listener interface was defined in the Fragment ). After this method, onCreate() is called.

Are fragments deprecated?

Register and create a developer profile to keep track of sessions you're interested in by saving them to My I/O.


1 Answers

No, you should not implement

public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState)

When a method is deprecated, you can (generally) safely use the replacement function instead. Check Fragment's definitions of onInflate:

public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState) {
        mCalled = true;
        final Activity hostActivity = mHost == null ? null : mHost.getActivity();
        if (hostActivity != null) {
            mCalled = false;
            onInflate(hostActivity, attrs, savedInstanceState);
        }
    }

 @Deprecated
    public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) {
        mCalled = true;
    }

As you can see, onInflate(Context context...) is an extension of onInflate(Activity activity...) and is backward compatible. By calling super.onInflate(context, attrs, savedInstanceState); inside your overridden method, you can safely assume that it will work on both API23 and earlier versions.

If I run my app on a < API23 machine, the replacement code is not called.

That seems strange, I can't reproduce it, my log is being executed with a code like this in a non-v23 machine:

@Override 
public void onInflate(Context context, AttributeSet attrs,
                                    Bundle savedInstanceState) {
        super.onInflate(context, attrs, savedInstanceState);
        Log.w(TAG, "I'm being executed");
    }

Make sure that:

  1. You're importing the support version of Fragment, android.support.v4.app.Fragment instead of android.app.Fragment and that you make use of getSupportFragmentManager() instead of getFragmentManager().
  2. You have the latest libraries of support-v4 and appcompat-v7 as well as compileSdkVersion 23 in your build.gradle

And when I run the app on an API23 machine, it appears that BOTH versions of the handler are called.

That can be explained by the onInflate(Context context...) code, where if it's called by an Activity, calls onInflate(Activity activity...)

EDIT

Regarding the update:

Native implementation of android.app.Fragment isn't supposed to be backward compatible. The code of android.app.Fragmentis generally much more simpler than that of android.support.v4.app.Fragment because of that fact.

In addition, there are some features in native implementation that cannot be introduced in support library either because it's hard by design or because it's not a priority for the developers. E.g. In native implementation, in the onInflate() source code there is some use of Transition to animate the entrance or exit of the new fragment. That is nowhere to be found in the support library.

like image 89
Sevle Avatar answered Sep 28 '22 08:09

Sevle