动态添加项目到FragmentGridPagerAdapter

时间:2014-07-14 17:37:43

标签: android fragmentpageradapter wear-os

我正在尝试显示包含4个条目的FragmentGridPagerAdapter,当视图滚动时,我想向适配器添加项目。

这是我的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;
}

}

这就是我在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
                }
            }
        });

当我将项目添加到适配器并调用notifyDataSetChanged()时,适配器刷新正常,但是当我滚动添加的页面时它会崩溃。

这是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)

在调用getFragment时,我打印了_data我的适配器的大小,调用getFragment时_data.size()的值正确为8。

在日志中,4是初始适配器大小的大小。 8是之后的期望大小。添加项目时不会崩溃,但只有在向新项目滚动卡片时才会崩溃。我究竟做错了什么?

编辑:的确,这似乎是适配器的notifyDataSetChanged函数中的一个省略。我打开了谷歌的错误报告,如果您认为需要修复它,请将其加星标记:

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

2 个答案:

答案 0 :(得分:3)

GridViewPager.populate()中的第873行是:

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

在设置适配器时看起来mRowScroll数组的长度是固定的,而在getRowCount()被触发时未notifyDataSetChanged()更新。实际上,如果您检查GridViewPager课程的其余部分,您会看到它仅在setAdapter()方法中分配:

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

简而言之,我认为这是GridViewPager中的一个错误,只要您想更新行数或列数,就可以通过再次调用setAdapter()来规避错误。

答案 1 :(得分:1)

最新的可穿戴支持库1.1应该已经修复了这个bug,最新的Android Wear 5.0版本已经发布了。