16

I'm really curious about how to determine (from an outer class) if a fragment's onCreateView() has already been called. I have searched for similar questions but found none.

For instance, is fragment.isAdded() a good indicator?

My first thought was simply fragment.getView() != null, but I'm not 100% sure it would be reliable as it seems, and I'm also slightly reluctant to use it (for no particular reason, I just tend to avoid nullity checks). I would be happy to find a workaround. Suggestions I had:

isAdded()

Return true if the fragment is currently added to its activity.

This line is quite ambiguous in my opinion; added is not attached, but neither created. It might refer to FragmentTransaction.add() (which is semantically wrong because you can have <fragment>s stuck in your layout without having to call add or replace).

Still, FragmentTransaction.add() documentation gives no info nor makes you think added -> created. I'd say no.

isVisible()

Return true if the fragment is currently visible to the user. This means it: (1) has been added, (2) has its view attached to the window, and (3) is not hidden.

Looks good, in the sense that isVisible() -> isCreated, but the third option makes it isCreated != isVisible. I just think of fragments inside a view pager: not all are visible, but the fragments near the currently visible fragment are added, created and alive, you can call methods on them. But for them, isVisible() == false. This is kind of too strict.

isInLayout()

Return true if the layout is included as part of an activity view hierarchy via the < fragment> tag. This will always be true when fragments are created through the < fragment> tag, except in the case where an old fragment is restored from a previous state and it does not appear in the layout of the current state.

I don't think this applies here.

getView() != null

Returns The fragment's root view, or null if it has no layout.

This still looks the one and only solution. I'd just like a confirmation about that.

Implement a callback

..to be called onCreateView() or, better, onViewCreated(). But:

  • I don't need to call something as soon as the fragment is created (why would you need that?), I need something to check at a given time;
  • One should define the opposite, say, onViewNotAvailableAnymore(), to make the check meaningful at all times;
  • I don't see how this would be different, or better, than getView != null.
natario
  • 24,954
  • 17
  • 88
  • 158

8 Answers8

8

Does Fragment.isAdded() imply that onCreateView has been called?

NO!! NO!! pause NOOOOOOO00000000000!!!!!

SIr

Fragment.isAdded() is a notification that your Fragment has been added to your Activity, end of story.

The add() method in FragmentTransaction has 3 different methods, all adds Fragment to an Activity ,and, two goes further to create your Fragments View and attach it to a Parent ViewGroup by the aid of LayoutInflater provided your first parameter is not 0 (id != 0)

To check if onCreateView() has been called you need to override onViewCreated().

getView() will always return null unless onCreateView() is done

your solution is check Fragment.isVisible()

FYI: There is nothing wrong that i see with the documentation. Its pretty clear sir.

Hope i am lucid Sir

Elltz
  • 10,730
  • 4
  • 31
  • 59
  • My "documentation" thoughts were just an edit I made in response to the other answer, which was not convincing to me. Apart from that, I am looking for ways to check if the view has been created from *outside* the fragment, e.g. from the outer activity. I wonder if `fragment.getView() != null` is the only (and best) way. – natario Sep 24 '15 at 21:32
  • well you can go for [Fragment.isVisible()](http://developer.android.com/reference/android/app/Fragment.html#isVisible%28%29) which will return true only if the fragment is added and has a parent. also you can have a look at `FragmentisInLayout ()` hope mine is convincing @mvai – Elltz Sep 24 '15 at 22:02
  • @mvai care to share your response & appreciations? – Elltz Sep 30 '15 at 02:00
  • Thank you @Elltz. I'm not 100% sure about `isVisible()`, for the reasons stated in my question (updated). I'm starting to believe that `getView() != null` is the only reliable way. I will wait until tomorrow to award the bounty - at least you said **no** to `isAdded()` ! :-) – natario Sep 30 '15 at 15:05
  • 2
    Has sir considered the possibility that the original sir is in fact a madam? – mrrrk Mar 29 '19 at 09:01
5

Assuming

  • you're not interested in whether the Fragment is visible
  • you want to know only if the onCreateView(...) method has been called by the Android framework
  • you need to use existing Fragment API methods to find out

then use

getView() != null

provided that you inflate the layout and return the View inside onCreateView(...) .

A non-Fragment-API approach is to add a callback in onCreate(...), which you then call in onCreateView() or later (in lifecycle) method.

Gunnar Karlsson
  • 28,350
  • 10
  • 68
  • 71
  • The listener approach is not what I'm asking for, since I don't want to call something on the fragment as soon as it is created (I don't see how one would need that), but rather check at a given time. Also that is like setting a static variable to true, but such a simple thing should be provided by the framework at least. I believe it is and it has to be `getView() != null`, so I currently agree with you. – natario Oct 01 '15 at 12:55
3

Please consider this approach as I did same like this:

Define an Interface with in your Fragment say:

public Interface IDoSomething{

  void intimateAfterOnCreateView();
}

Now, call this method with in onStart() of a fragment as according to life cycle this method will be called after the onCreateView(). Outside from this fragment just implement IDoSomething and you will get an overrided method(intimateAfterOnCreateView()) automatically.

Now this method's execution will show that onCreateView() has been called.

I just want to share my knowledge, may be it helps.

Elltz
  • 10,730
  • 4
  • 31
  • 59
Akber
  • 521
  • 4
  • 10
  • 1
    As other answers here, I believe you are missing the piece where you set this "availability" back to false. This is like setting a public static boolean variable to `true` (and then check `if MyFragment.created`), but when should I set it back to `false`, and how is this better/different than `getView() != null`? – natario Oct 01 '15 at 12:46
2

It can be done using interface. make an interface OnCreateViewListerner

public interface OnViewCreatedListener
    {
        void onCreateCalled();
    }

create a static object of OnViewCreatedListener in your Fragment and initialize it within in your Outer class and Outer class implement this interface like

    public class CustomClass implements OnViewCreatedListener{
        @Override
        public void onCreateCalled() {

        }
    public void  initializeInterface()
    {
        FragmentTest.listerner = this;
    }
    .....

    }

then override your onCreateView() method and write this

public class FragmentTest extends Fragment{

public static OnViewCreatedListener listerner;
    View mView;
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//        if (container == null)

        if(listerner!= null)
        {
            listerner.onCreateCalled();
        }
        mView = inflater.inflate(R.layout.fragment_product, container, false);


        return mView;
    }


    }

Hope this will help you.

Ramesh Kumar
  • 1,229
  • 14
  • 24
  • I would do this onViewCreated() actually, but you are missing the piece where you call, like, onViewNotAvailableAnymore() . I don't want a callback, but rather a way to know, from a given `fragment`, if its onCreateView() has yet been called. I believe `getView != null` is much simpler. – natario Oct 01 '15 at 12:44
  • it's upto you where you want to call this callback, when you don't want to call the callback then just FragmentTest.listener= null; then it will call the listener. – Ramesh Kumar Oct 01 '15 at 13:19
1

If isAdded() on a Fragment returns true, it doesn't mean that the onCreateView() has been called. In fact, isAdded returns true even during the onAttach callback, that is called before the onCreate().

Mimmo Grottoli
  • 5,758
  • 2
  • 17
  • 27
0

I would go with extending the Fragment class and adding a public method that you can use to reach from outer of your custom Fragment Class.

When the onCreateView() is called, you can set a boolean value to true and according to your architecture, you can set it to false back again when it's in onPause() or onStop() or onDestroyView() or onDestroy() or onDetach(), up to you.

I don't think the methods you mentioned in your question will provide you exactly what you need.

osayilgan
  • 5,873
  • 7
  • 47
  • 68
0

How can I know that onCreateView has been called from an outer class?

You need to create interface inside your fragment and implement it in the container activity (let's say MainActivity).

1. First create an interface inside your fragment:

// Container activity must implement this interface
public interface OnCreateViewCalledListener {
    void OnCreateViewCalled(String someData);
}

2. Next implement the interface inside your container activity (lets say it is MainActivity) and call it's method:

public class MainActivity extends AppCompatActivity implements
        YourFragment.OnCreateViewCalledListener {
...

@Override
    public void OnCreateViewCalled(String someData) {
      Toast.makeText(MainActivity.this, "OnCreateView was called and passed " + someData)
    }

3. Then you need to check if MainActivity implements interface callbacks (this step is crucial to make it work properly):

//Using onAttach method to check that activity has implemented callbacks
@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    // Make sure that container activity has implemented
    // the callback interface. If not, it throws an exception
    try {
        mCallback = (OnCreateViewCalledListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString()
                + " must implement OnCreateViewCalledListener");
    }
}

4. And finally you need to trigger the callback inside onCreateView:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        mCallback.OnCreateViewCalled("Some useful data");
        ...
    }

That's it!

EDIT:

To let other class know that onCreateView was called, please use the onCreateViewCalled() callback inside the MainActivity (e.g. use another interface to trigger callback in other class). Also it is not mandatory to pass data into the OnCreateViewCalled()

Ivan V
  • 3,024
  • 4
  • 26
  • 36
-1

Does Fragment.isAdded() imply that onCreateView has been called?

YES

isAdded() Return true if the fragment is currently added to its activity. (Implicitly onCreateView() has been called).

Jorgesys
  • 124,308
  • 23
  • 334
  • 268
  • This documentation line is quite ambiguous in my opinion; *added* is not *attached*, but neither *created*. It might refer to `FragmentTransaction#add()` (which is semantically wrong because you can have ``s stuck in your layout without having to call `add` or `replace`). In addition, `add` documentation is ambiguous too and it is not clear that onCreateView has already been called there. – natario Sep 18 '15 at 18:12