我正在开发一个项目,我正在使用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);
}
}
}
提前致谢!!!
答案 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。