3

I have an Activity with a single Fragment inside of it. Inside this Fragment I have a ViewPager that pages Fragments. This makes the paged Fragments children of the Fragment inside the Activity. Basically like this:

    Activity
       |
       |
    Fragment
       |
   (ViewPager)
    |       |
    |       |
Fragment  Fragment

Every so often, seemingly at random, the Fragments inside the ViewPager will not display. I looked at the View hierarchy in Hierarchy Viewer and noticed that when this happens the child Fragments (at the bottom of my picture) are in the layout, but the root View of the children has zero height and zero width (as does every View in the hierarchy tree from there down to the leaf Views). The ViewPager does have height and width, but the Fragments it pages do not.

If I rotate the device at this point, my child Fragments show up!

I'm at a loss as to why this is happening. The Adapter I'm using with the ViewPager requires a FragmentManager, and I'm using the one from the Fragment inside the Activity by calling getChildFragmentManager(). I feel like I'm doing everything I'm supposed to do, not sure where to look next on this one.

UPDATE:

Interestingly enough, if I put the code that attaches the Adapter to the ViewPager in a Runnable and post it to a Handler the issue is 100% reproducible. i.e.

class MyFragment extends Fragment {

  @Override 
  public void onActivityCreated(Bundle b) {
    super.onActivityCreated(b);

    runPager = new Runnable() {

      @Override 
      public void run() {
        viewPager.setAdapter(adapter);
      }

    };

    handler.post(runPager);
  }
}
Christopher Perry
  • 38,891
  • 43
  • 145
  • 187

2 Answers2

1

I figured this out. If anyone else runs into this, make sure you aren't manipulating UI components on a background thread or weird things happen. In my case I was doing Bitmap manipulation on a background thread with RxJava, but I forgot this line:

.observeOn(AndroidSchedulers.mainThread());

So when I put the bitmap in my View in the Subscriber, it was on a background thread. Easy mistake to make.

Christopher Perry
  • 38,891
  • 43
  • 145
  • 187
0

You are right with your assumption. Android is quite annoying to handle regarding the mighty main thread vs. worker threads.

For example if you trigger a SwipeRefreshLayout which does a network fetch, and the returning callback is invoked on the background where you just do setRefreshing(false) this may not show you any warning but lead to strange side effects.

If you are using child fragments inside a ViewPager this fragment might be working okay, but the size is reduced to (0, 0) or the offset of the fragments root layout is set to the screenWidth. So always doublecheck if there is a background thread accessing the user interface.

Martin Mlostek
  • 2,755
  • 1
  • 28
  • 57
  • Thank You! You save my Life!!! I update come data with kotlin coroutines in Background. And some page size in (0.0). After move my code to: GlobalScope.async(Dispatchers.Main) { ... } - problem is gone!! – Zanael Mar 02 '19 at 17:45