【问题标题】:ArrayIndexOutOfBoundException in Realm领域中的 ArrayIndexOutOfBoundException
【发布时间】:2017-02-27 08:32:28
【问题描述】:

我正在做一个项目,其中我正在使用 Realm 数据库,现在我正在尝试从数据库中获取一个值,它工作正常 3-4 次然后代码崩溃了。 错误信息如下

E/AndroidRuntime: 致命异常: main 进程:in.mumbaitravellers.mtleaders,PID:22340 java.lang.ArrayIndexOutOfBoundsException:rowIndex > 可用行:3 > 3 在 io.realm.internal.TableView.nativeGetSourceRowIndex(本机方法) 在 io.realm.internal.TableView.getSourceRowIndex(TableView.java:161) 在 io.realm.RealmResults.get(RealmResults.java:114) 在 in.mumbaitravellers.mtleaders.adapters.ExpenseAdapter.onBindViewHolder(ExpenseAdapter.java:55) 在 android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5471) 在 android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5504) 在 android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4741) 在 android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4617) 在 android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1994) 在 android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1390) 在 android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1353) 在 android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:574) 在 android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3028) 在 android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2906) 在 android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3283) 在 android.view.View.layout(View.java:16646) 在 android.view.ViewGroup.layout(ViewGroup.java:5440) 在 android.support.design.widget.CoordinatorLayout.layoutChild(CoordinatorLayout.java:1037) 在 android.support.design.widget.CoordinatorLayout.onLayoutChild(CoordinatorLayout.java:747) 在 android.support.design.widget.ViewOffsetBehavior.onLayoutChild(ViewOffsetBehavior.java:42) 在 android.support.design.widget.AppBarLayout$ScrollingViewBehavior.onLayoutChild(AppBarLayout.java:1156) 在 android.support.design.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:760) 在 android.view.View.layout(View.java:16646) 在 android.view.ViewGroup.layout(ViewGroup.java:5440) 在 android.widget.FrameLayout.layoutChildren(FrameLayout.java:336) 在 android.widget.FrameLayout.onLayout(FrameLayout.java:273) 在 android.view.View.layout(View.java:16646) 在 android.view.ViewGroup.layout(ViewGroup.java:5440) 在 android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743) 在 android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586) 在 android.widget.LinearLayout.onLayout(LinearLayout.java:1495) 在 android.view.View.layout(View.java:16646) 在 android.view.ViewGroup.layout(ViewGroup.java:5440) 在 android.widget.FrameLayout.layoutChildren(FrameLayout.java:336) 在 android.widget.FrameLayout.onLayout(FrameLayout.java:273) 在 android.view.View.layout(View.java:16646) 在 android.view.ViewGroup.layout(ViewGroup.java:5440) 在 android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743) 在 android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586) 在 android.widget.LinearLayout.onLayout(LinearLayout.java:1495) 在 android.view.View.layout(View.java:16646) 在 android.view.ViewGroup.layout(ViewGroup.java:5440) 在 android.widget.FrameLayout.layoutChildren(FrameLayout.java:336) 在 android.widget.FrameLayout.onLayout(FrameLayout.java:273) 在 com.android.internal.policy.PhoneWindow$DecorView.onLayout(PhoneWindow.java:2678) 在 android.view.View.layout(View.java:16646) 在 android.view.ViewGroup.layout(ViewGroup.java:5440) 在 android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2183) 在 android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1943) 在 android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1119) 在 android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6060) 在 android.view.Choreographer$CallbackRecord.run(Choreographer.java:858) 在 android.view.Choreographer.doCallbacks(Choreographer.java:670) 在 android.view.Choreographer.doFrame(Choreographer.java:606) 在 android.view.Choreographer$FrameDisplayEventReceiver.run(Choreog W/art:暂停所有线程耗时:9.933ms

sn-p代码如下:

public class ExpenseAdapter extends RealmRecyclerViewAdapater<Expense> {

final Context context;
private Realm realm;
private LayoutInflater inflater;

public ExpenseAdapter(Context context) {
    this.context = context;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    // inflate a new card view
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.expense_recycler_view, parent, false);
    // view.setOnCreateContextMenuListener(this);
    return new CardViewHolder(view);
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, final int position) {

    realm = RealmController.getInstance().getRealm();

    final Expense expense = getItem(position);
    final Tour tour = new Tour();
    final CardViewHolder holder = (CardViewHolder) viewHolder;
    String s = "";

    RealmResults<Tour> r = realm.where(Tour.class).findAll();
    realm.beginTransaction();
    s = r.get(position).getEventId();
    realm.commitTransaction();


    holder.textExpense.setText(expense.getAmount() + " E: " + expense.getEventId());
    holder.textDescription.setText(expense.getDescription() + " T: " + s);

    holder.card.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View content = inflater.inflate(R.layout.activity_add_new_expense, null);
            final EditText editAmount = (EditText) content.findViewById(R.id.edtxt_expense);
            final EditText editDescription = (EditText) content.findViewById(R.id.edtxt_description);

            editAmount.setText(expense.getAmount());
            editDescription.setText(expense.getDescription());

            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setView(content)
                    .setTitle("Edit Event")
                    .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {

                            RealmResults<Expense> results = realm.where(Expense.class).findAll();

                            realm.beginTransaction();
                            results.get(position).setAmount(editAmount.getText().toString());
                            results.get(position).setDescription(editDescription.getText().toString());

                            realm.commitTransaction();

                            notifyDataSetChanged();
                        }
                    })
                    .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }
                    });
            AlertDialog dialog = builder.create();
            dialog.show();
        }
    });

}

@Override
public int getItemCount() {
    if (getRealmAdapter() != null) {
        return getRealmAdapter().getCount();
    }
    return 0;
}

public static class CardViewHolder extends RecyclerView.ViewHolder {

    public CardView card;
    public TextView textExpense;
    public TextView textDescription;

    public CardViewHolder(View itemView) {
        // standard view holder pattern with Butterknife view injection
        super(itemView);

        card = (CardView) itemView.findViewById(R.id.card_expense);
        textExpense = (TextView) itemView.findViewById(R.id.text_amount);
        textDescription = (TextView) itemView.findViewById(R.id.text_description);
    }

}
}

提前致谢!!!

【问题讨论】:

  • 您的 ide 是否显示错误发生在哪一行?在我看来,第 31 行(在您的代码中)可能是您的错误的原因。因为这是从领域实例中检索任何数据的唯一行
  • @Radinator 错误发生在这些行 RealmResults r = realm.where(Tour.class).findAll();领域.beginTransaction(); s = r.get(位置).getEventId();领域.commitTransaction();
  • 然后尝试调试您的应用程序并打印 r.Count() 我认为您的问题是 position 中的值大于 RealmResult中的项目数量>
  • @Radinator 从技术上讲,他只需要不手动调用adapter.notifyDataSetChanged()

标签: android realm


【解决方案1】:

这就是为什么:

RealmResults<Expense> results = realm.where(Expense.class).findAll();
realm.beginTransaction();
results.get(position).setAmount(editAmount.getText().toString());
results.get(position).setDescription(editDescription.getText().toString());
realm.commitTransaction();
notifyDataSetChanged(); // <--------- this causes the crash

问题:

1.) 如果您在事务中操作结果集,那么您应该在事务中进行查询

realm.beginTransaction();
RealmResults<Expense> results = realm.where(Expense.class).findAll();

2.) 你应该避免创建不必要的代理,你应该只获取一次元素。

Expense expense = results.get(position);
expense.setAmount(editAmount.getText().toString());
expense.setDescription(editDescription.getText().toString());

3.) 从 0.89.0(但最高到 3.0.0),RealmResults 仅在下一个事件循环时更新,之后调用 RealmChangeListener。这是由RealmRecyclerViewAdapter 自动管理的,这意味着如果你进行 UI 线程本地提交(你不应该,但你可以),那么你应该手动调用 adapter.notifyDataSetChanged(),你应该注册一个RealmChangeListener 并从那里调用它(这由RealmRecyclerViewAdapter 内部管理)。

所以基本上,删除notifyDataSetChanged()这一行


我还看到你有一个RealmController.getInstance() 调用,我猜你使用this guide from AndroidHive 作为你的领域驱动应用程序的基础。

那个指南是过时的垃圾,我推荐使用我的:

How to use Realm for Android like a champ, and how to tell if you're doing it wrong

连同对应的source example

【讨论】:

    猜你喜欢
    • 2011-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多