领域

时间:2016-10-18 07:20:23

标签: android realm

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

  

E / AndroidRuntime:致命异常:主要                     处理:in.mumbaitravellers.mtleaders,PID:22340                     java.lang.ArrayIndexOutOfBoundsException:rowIndex>可用行:3> 3                         at io.realm.internal.TableView.nativeGetSourceRowIndex(Native Method)                         at io.realm.internal.TableView.getSourceRowIndex(TableView.java:161)                         在io.realm.RealmResults.get(RealmResults.java:114)                         at 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

代码段如下:

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);
    }

}
}

提前致谢!!!

1 个答案:

答案 0 :(得分:3)

这就是原因:

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作为您的Realm驱动的应用程序的基础。

该指南是过时的垃圾,我建议使用我的:

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

连同相应的source example