Reputation: 1866
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
Upvotes: 4
Views: 2358
Reputation: 3232
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.
Upvotes: 1
Reputation: 55380
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.
Upvotes: 3