4

I'm trying to display a FragmentGridPagerAdapter with 4 entries, and when the view scrolls I want to add items to the adapter.

This is my FragmentPagerAdapter:

public class MyPagerAdapter extends FragmentGridPagerAdapter {

private final Context _ctx;
private HashMap<Integer, Entry> _data;

public MyPagerAdapter(Context context, FragmentManager fm, HashMap<Integer, Entry> tidatals) {
    super(fm);
    _ctx = context;
    _data = data;
}

public void addEntry(Entry entry)
{
    _data.put(_data.size(), entry);
    this.notifyDataSetChanged();
}


@Override
public Fragment getFragment(int i, int i2) {

    CardFragment fragment = CardFragment.create("Card", _data.get(i).getPrettyText());
    fragment.setCardGravity(Gravity.BOTTOM);
    fragment.setExpansionEnabled(true);
    return fragment;
}

@Override
public int getRowCount() {
    return _data.size();
}

@Override
public int getColumnCount(int i) {
    return 1;
}

}

And this is how I add data to the adapter in my Main Wear Activity:

//In onCreate: 
    _data = new HashMap<Integer, Entry>();
    _adapter = new TILPagerAdapter(this, getFragmentManager(), _data);
    _pager.setAdapter(_adapter);

//When I finally get my data:
...
// Do stuff, get datas in 'data' variable
MainWear.this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                 boolean firstData = _data.isEmpty();
                for(TILEntry entry : data.values())
                {
                    _adapter.addEntry(entry);
                }
                if(firstData){
                    _pager.setAdapter(_adapter);
                    switchViewToResults(); // Sets pager to visible
                }
            }
        });

When I add items into the adapter and call notifyDataSetChanged(), the adapter refreshes fine, however it crashes when I scroll towards the added pages.

Here is the stacktrace:

E/InputEventReceiver﹕ Exception dispatching input event.
E/MessageQueue-JNI﹕ Exception in MessageQueue callback: handleReceiveCallback
E/MessageQueue-JNI﹕ java.lang.ArrayIndexOutOfBoundsException: length=4; index=4
            at android.support.wearable.view.GridViewPager.populate(GridViewPager.java:873)
            at android.support.wearable.view.GridViewPager.setCurrentItemInternal(GridViewPager.java:584)
            at android.support.wearable.view.GridViewPager.handlePointerUp(GridViewPager.java:1990)
            at android.support.wearable.view.GridViewPager.onTouchEvent(GridViewPager.java:1492)
            at android.view.View.dispatchTouchEvent(View.java:7846)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2209)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1944)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2215)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1958)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2215)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1958)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2215)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1958)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2215)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1958)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2085)
            at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1532)
            at android.app.Activity.dispatchTouchEvent(Activity.java:2468)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2033)
            at android.view.View.dispatchPointerEvent(View.java:8026)
            at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:3989)
            at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3868)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3433)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3483)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3452)
            at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3559)
            at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3460)
            at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3616)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3433)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3483)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3452)
            at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3460)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3433)
            at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5589)
            at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5569)
            at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5540)
            at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5669)
            at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
            at android.os.MessageQueue.nativePollOnce(Native Method)
            at android.os.MessageQueue.next(MessageQueue.java:138)
            at android.os.Looper.loop(Looper.java:123)
            at android.app.ActivityThread.main(ActivityThread.java:5026)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
            at dalvik.system.NativeStart.main(Native Method)
D/AndroidRuntime﹕ Shutting down VM
W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0xadb04d70)
E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: til.wear.robineisenberg.til_wear, PID: 5808
    java.lang.ArrayIndexOutOfBoundsException: length=4; index=4
            at android.support.wearable.view.GridViewPager.populate(GridViewPager.java:873)
            at android.support.wearable.view.GridViewPager.setCurrentItemInternal(GridViewPager.java:584)
            at android.support.wearable.view.GridViewPager.handlePointerUp(GridViewPager.java:1990)
            at android.support.wearable.view.GridViewPager.onTouchEvent(GridViewPager.java:1492)
            at android.view.View.dispatchTouchEvent(View.java:7846)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2209)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1944)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2215)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1958)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2215)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1958)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2215)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1958)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2215)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1958)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2085)
            at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1532)
            at android.app.Activity.dispatchTouchEvent(Activity.java:2468)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2033)
            at android.view.View.dispatchPointerEvent(View.java:8026)
            at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:3989)
            at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3868)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3433)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3483)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3452)
            at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3559)
            at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3460)
            at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3616)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3433)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3483)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3452)
            at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3460)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3433)
            at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5589)
            at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5569)
            at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5540)
            at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5669)
            at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
            at android.os.MessageQueue.nativePollOnce(Native Method)
            at android.os.MessageQueue.next(MessageQueue.java:138)
            at android.os.Looper.loop(Looper.java:123)
            at android.app.ActivityThread.main(ActivityThread.java:5026)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
            at dalvik.system.NativeStart.main(Native Method)

I printed the size of _data my Adapter when getFragment is called, _data.size() is correctly worth 8 when getFragment is called.

In the log, 4 is the size of the initial adapter size. 8 is the desired size afterwards. It doesn't crash upon adding the items, but only upon scrolling through the cards towards the new items. What am I doing wrong?

EDIT: Indeed, this seems to be an ommission in the notifyDataSetChanged function of the adapter. I opened a bug report w/ Google, star it if you think this needs to be fixed:

https://code.google.com/p/android/issues/detail?id=73846&thanks=73846&ts=1405945122

Robin Eisenberg
  • 1,836
  • 18
  • 26

2 Answers2

3

Line 873 in GridViewPager.populate() is this:

    this.mRowScrollX[row] = computePageLeft(...);

Looks like the length of the mRowScroll array is fixed when setting the adapter, and not updated from getRowCount() when notifyDataSetChanged() is fired. Indeed, if you check the rest of the GridViewPager class, you'll see it's only assigned in the setAdapter() method:

    this.mExpectedRowCount = this.mAdapter.getRowCount();
    this.mRowScrollX = new int[this.mExpectedRowCount];

In short, I would think this is a bug in GridViewPager, which could be circumvented by calling setAdapter() again whenever you want to update the row or column count.

matiash
  • 54,791
  • 16
  • 125
  • 154
1

This bug should have been fixed in the latest wearable support library 1.1, that came out with the latest Android Wear 5.0 release.

Wayne Piekarski
  • 3,203
  • 18
  • 19
  • Just tried it out, it works for me here on my LG-G Watch. Thank you for the information. Just a quick question: is it normal that the bug report I submitted for this issue is not marked as "resolved"? Is there an other issue tracker that I should be posting to in this case? – Robin Eisenberg Dec 29 '14 at 15:54