Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the view of a Fragment outside of OnCreateView()

I have a Fragment with a TableLayout. The data in the table is from a SQLite db. The SQLite db is populated from a RESTful webservice in an AsyncTask in the MainActivity. The Fragment must wait for the task to complete before populating the table. The Fragment listens for the task onPostExecute() method to be called. When it is, the method onLoadAndStoreComplete() in the Fragment is called. This all works.

I need to get a view of a TableLayout outside the OnCreateView() method of a Fragment. If I could get the View of the fragment in onLoadAndStoreComplete that would get me there.

Same code as here. I've got mContext from the MainActivity, but that has no getView() method associated with it.

I've tried:
- making a class member rootView and assigning in onCreateView(), but in onLoadAndStoreComplete(), it is null.
- making a class member tableLayout and assigning in onCreateView(), but in onLoadAndStoreComplete(), it is null.
- calling this.getView() again in onLoadAndStoreComplete(), but it returns null.
- calling the inflator inside onLoadAndStoreComplete(), which works, but then I don't know what to use for container in the .inflate() call

I don't understand why the class member values of rootView and tableLayout are null in onLoadAndStoreComplete()

public class MyFragment extends Fragment implements OnLoadAndStoreCompleteListener {

private TableLayout tableLayout;
private View rootView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  Bundle savedInstanceState) {
        mContext = this.getActivity();
        rootView = inflater.inflate(R.layout.fragment_permits, container, false); // this works
        tableLayout = (TableLayout) rootView.findViewById(R.id.main_table); // and this
        ...
    }

    @Override
    public void onLoadAndStoreComplete() {

       // rootView is null, ie not remembered from OnCreateView

        View view =  getView(); // null

        LayoutInflater inflater = LayoutInflater.from(getActivity());
      rootView = inflater.inflate(R.layout.fragment_permits, container, false); // container? don't know what it should be

        // tableLayout is null
        tableLayout.addView(tableRow, new TableLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
    }
    ...
}
like image 294
Al Lelopath Avatar asked Apr 13 '15 14:04

Al Lelopath


People also ask

What is the difference between onCreate () and onCreateView () lifecycle methods in fragment?

onCreate(Bundle) called to do initial creation of the fragment. onCreateView(LayoutInflater, ViewGroup, Bundle) creates and returns the view hierarchy associated with the fragment. onActivityCreated(Bundle) tells the fragment that its activity has completed its own Activity. onCreate() .

What is difference between onCreateView and onViewCreated in fragment?

onCreate() is called to do initial creation of the fragment. onCreateView() is called by Android once the Fragment should inflate a view. onViewCreated() is called after onCreateView() and ensures that the fragment's root view is non-null .

What is called after onCreateView?

The onActivityCreated() method is called after onCreateView() and before onViewStateRestored() . onDestroyView() : Called when the View previously created by onCreateView() has been detached from the Fragment . This call can occur if the host Activity has stopped, or the Activity has removed the Fragment .

Is onCreate called before onCreateView?

The onCreate() is called first, for doing any non-graphical initialisations. Next, you can assign and declare any View variables you want to use in onCreateView() .


4 Answers

If I understand your code correctly, there is something wrong either with your code not respecting Fragment lifecycle or a different Fragment instance failure.

A. Lifecycle problem

Android framework expects your Fragment to create its view inside onCreateView() method. View becomes available after framework calls this method.

It is possible that your code called onLoadAndStoreComplete() before onCreateView(), and this has caused the problem.

You need to extract method for populating actual views with data, as it can have 2 entry points. Please see code below:

public class MyFragment extends Fragment implements OnLoadAndStoreCompleteListener {
    private TableLayout tableLayout;
    private View rootView;
    private SomeDataClass loadedData;

    @Override
    public View onCreateView(LayoutInflater inflater, 
                             ViewGroup container,
                             Bundle savedInstanceState) {
        mContext = this.getActivity();
        rootView = inflater.inflate(R.layout.fragment_permits, container, false); 
        tableLayout = (TableLayout) rootView.findViewById(R.id.main_table);

        updateUi(); // If onLoadAndStoreComplete() was already called
                    // this will plug newly created view to returned data
    }

    @Override
    public void onLoadAndStoreComplete() {
        loadedData = ...; // Save loaded data here
        updateUi(); // If onCreateView() was already called
                    // this will plug loaded data to the view
    }


    private void updateUi() {
        if (rootView == null) { // Check if view is already inflated
            return; 
        }

        if (loadedData != null) {
            // View is already inflated and data is ready - update the view!
            ...
        }
    }
}

B. Different instance failure

This may occur when you're operating on 2 different instances of before mentioned fragment.

At first everything will look in order: onCreateView() called before onLoadAndStoreComplete(). Therefore check these:

  • Log/debug default constructor calls for your Fragment. You are expecting to get one call for your fragment during create/load flow.
  • Check whether object that called onCreateView() is the exact same object that called onLoadAndStoreComplete(), you can use System.identityHashCode(this), getting different values within this two methods is a bad sign

If this is what happens, cause is probably hidden a bit deeper, and without code I cannot give you accurate advice on this. How do you create your fragment? Via XML or manually then adding via FragmentManager or via ViewPager?

like image 107
jskierbi Avatar answered Oct 23 '22 15:10

jskierbi


getView() gives rootView of Fragment which is returned from onCreatedView(). So if onLoadAndStoreComplete() gets called before onCreatedView() is finished (which it can't return your rootView), you get null since there is not view created yet.


I have tried calling getView() inside onViewCreated() which is NOT null:

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        View viewer=getView();
        if(viewer==null){
            Itu.showToast("null",getActivity(), Toast.LENGTH_LONG);
        }else{
            Itu.showToast(viewer.toString(),getActivity(), Toast.LENGTH_LONG);//This is called
        }
    }
like image 29
Jemshit Iskenderov Avatar answered Oct 23 '22 15:10

Jemshit Iskenderov


From your code fragment, if fields rootView and tableLayout are initialized after calling onCreateView(..), if both fields are not setted to null after that then they must be not null when you call onLoadAndStoreComplete(..).

Said that, I think you are calling that method in a different instance of your fragment. Review your activity code and check that you are using the same instance from the fragment all the time.

like image 2
juanhl Avatar answered Oct 23 '22 15:10

juanhl


I need to get a view of a TableLayout outside the OnCreateView() method of a Fragment. If I could get the View of the fragment in onLoadAndStoreComplete that would get me there.

Try changing the definition of onLoadAndStoreComplete to take a View and then passing in a view of the fragment.

like image 1
Joshua Byer Avatar answered Oct 23 '22 17:10

Joshua Byer