我有一个recyclerView,它填充了来自SQLite数据库的数据。每个项目都有一个按钮,可以删除数据库中的标志,从而从recyclerView列表中消失。
我得到的问题是,当我尝试删除不同订单中的项目时,应用程序崩溃并引用错误/未知索引作为原因。
以下是我的recyclerView的(部分)代码,我认为问题在于:
@Override
public BookmarksDetailRecycleAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View itemLayoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.dua_detail_item_card, null);
// create ViewHolder
mHolder = new ViewHolder(itemLayoutView);
return mHolder;
}
public void deleteRow(int position){
mDuaData.remove(position); // this will remove row of data
notifyItemRemoved(position); // this will do the animation of removal
notifyItemRangeChanged(position, mDuaData.size()); // From GreenTech email
// dataSetChanged();
}
@UiThread
protected void dataSetChanged() {
notifyDataSetChanged();
}
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder mHolder, int position){//final RecyclerView rv) {
// - get data from your itemsData at this position
// - replace the contents of the view with that itemsData
final int finalPosition = position;
mHolder.tvDuaNumber.setText(mDuaData.get(position).getReference() + "");
mHolder.tvDuaArabic.setText(Html.fromHtml(mDuaData.get(position).getArabic()));
final Spannable translation = new SpannableString(mDuaData.get(position).getTranslation());
mHolder.tvDuaTranslation.setText(translation);
if (mDuaData.get(position).getBook_reference() != null)
mHolder.tvDuaReference.setText(Html.fromHtml(mDuaData.get(position).getBook_reference()));
else
mHolder.tvDuaReference.setText("null");
if (mDuaData.get(position).getFav()) {
mHolder.favButton.setText("{faw-star}");
} else {
mHolder.favButton.setText("{faw-star-o}");
}
final ViewHolder finalmHolder = mHolder;
mHolder.shareButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View convertView) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT,
myToolbarTitle + "\n\n" +
finalmHolder.tvDuaArabic.getText() + "\n\n" +
finalmHolder.tvDuaTranslation.getText() + "\n\n" +
finalmHolder.tvDuaReference.getText() + "\n\n" +
convertView.getResources().getString(R.string.action_share_credit)
);
intent.setType("text/plain");
convertView.getContext().startActivity(
Intent.createChooser(
intent,
convertView.getResources().getString(R.string.action_share_title)
)
);
}
});
finalmHolder.favButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
boolean isFav = false;
Log.d("K12_isFav", "isFav: " + isFav);
int sql_position = Integer.parseInt(finalmHolder.tvDuaNumber.getText().toString());
Log.d("K12_sqlPosition", sql_position + "");
deleteRow(finalPosition);
Resources resources = v.getResources();
String snack_begin = resources.getString(R.string.snackbar_text_begin);
String snack_end = resources.getString(R.string.snackbar_text_end);
String snack_action = resources.getString(R.string.snackbar_action).toUpperCase();
// Following snippet taken from:
// http://developer.android.com/training/basics/data-storage/databases.html#UpdateDbRow
mDbHelper = new ExternalDbOpenHelper(v.getContext().getApplicationContext());
SQLiteDatabase db = mDbHelper.getReadableDatabase();
// New value for one column
ContentValues values = new ContentValues();
values.put(HisnDatabaseInfo.DuaTable.FAV, isFav);
// Which row to update, based on the ID
String selection = HisnDatabaseInfo.DuaTable.DUA_ID + " LIKE ?";
String[] selectionArgs = {String.valueOf(finalmHolder.tvDuaNumber.getText().toString())};
Log.d("K12_selectionArgs", "tvDuaNumber: " + String.valueOf(finalmHolder.tvDuaNumber.getText().toString()));
int count = db.update(
HisnDatabaseInfo.DuaTable.TABLE_NAME,
values,
selection,
selectionArgs);
if (count == 1) {
if (isFav) {
finalmHolder.favButton.setText("{faw-star}");
} else {
finalmHolder.favButton.setText("{faw-star-o}");
}
}
if (getItemCount() == 0) {
// I don't even know if this block is needed. Review once you have some sleep.
}
}
});
}
// inner class to hold a reference to each item of RecyclerView
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView tvDuaNumber;
public TextView tvDuaArabic;
public TextView tvDuaTranslation;
public TextView tvDuaReference;
public IconicsButton shareButton;
public IconicsButton favButton;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
tvDuaNumber = (TextView) itemLayoutView.findViewById(R.id.txtDuaNumber);
tvDuaArabic = (TextView) itemLayoutView.findViewById(R.id.txtDuaArabic);
tvDuaTranslation = (TextView) itemLayoutView.findViewById(R.id.txtDuaTranslation);
tvDuaReference = (TextView) itemLayoutView.findViewById(R.id.txtDuaReference);
shareButton = (IconicsButton) itemLayoutView.findViewById(R.id.button_share);
favButton = (IconicsButton) itemLayoutView.findViewById(R.id.button_star);
tvDuaArabic.setTypeface(sCachedTypeface);
tvDuaArabic.setTextSize(prefArabicFontSize);
tvDuaTranslation.setTextSize(prefOtherFontSize);
tvDuaReference.setTextSize(prefOtherFontSize);
}
}
// Return the size of your itemsData (invoked by the layout manager)
@Override
public int getItemCount() {
return mDuaData == null ? 0 : mDuaData.size();
}
可以在Github上查看适配器的完整代码。
以下是错误的logcat报告:
12-06 12:01:08.288 7104-7135/com.khalid.hisnulmuslim D/OpenGLRenderer: endAllStagingAnimators on 0x67b72220 (RippleDrawable) with handle 0x67b3ad40
12-06 12:01:08.288 7104-7135/com.khalid.hisnulmuslim D/OpenGLRenderer: endAllStagingAnimators on 0x7e596df8 (ListView) with handle 0x67b3ad28
12-06 12:01:08.308 7104-7104/com.khalid.hisnulmuslim I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@10886dfe time:55529721
12-06 12:01:10.968 7104-7104/com.khalid.hisnulmuslim D/K12_isFav: isFav: false
12-06 12:01:10.968 7104-7104/com.khalid.hisnulmuslim D/K12_sqlPosition: 3
12-06 12:01:10.978 7104-7104/com.khalid.hisnulmuslim D/K12_selectionArgs: tvDuaNumber: 3
12-06 12:01:12.573 7104-7104/com.khalid.hisnulmuslim D/K12_isFav: isFav: false
12-06 12:01:12.573 7104-7104/com.khalid.hisnulmuslim D/K12_sqlPosition: 1
12-06 12:01:12.583 7104-7104/com.khalid.hisnulmuslim D/K12_selectionArgs: tvDuaNumber: 1
12-06 12:01:14.228 7104-7104/com.khalid.hisnulmuslim D/K12_isFav: isFav: false
12-06 12:01:14.228 7104-7104/com.khalid.hisnulmuslim D/K12_sqlPosition: 4
12-06 12:01:14.228 7104-7104/com.khalid.hisnulmuslim D/AndroidRuntime: Shutting down VM
12-06 12:01:14.233 7104-7104/com.khalid.hisnulmuslim E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.khalid.hisnulmuslim, PID: 7104
java.lang.IndexOutOfBoundsException: Invalid index 2, size is 2
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.remove(ArrayList.java:403)
at com.khalid.hisnulmuslim.adapter.BookmarksDetailRecycleAdapter.deleteRow(BookmarksDetailRecycleAdapter.java:90)
at com.khalid.hisnulmuslim.adapter.BookmarksDetailRecycleAdapter$2.onClick(BookmarksDetailRecycleAdapter.java:160)
at android.view.View.performClick(View.java:4789)
at android.view.View$PerformClick.run(View.java:19881)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5294)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:114)
我一直试图解决这个问题,但我真的不知道问题是什么。将不胜感激任何帮助。
感谢。
答案 0 :(得分:0)
有关onBindViewHolder
请注意,与ListView不同,RecyclerView不会调用此方法 再次,如果项目的位置在数据集中发生变化,除非 项目本身无效或无法确定新职位。 因此,您应该只使用position参数 获取此方法中的相关数据项,不应保留 它的副本。 如果您稍后需要某个项目的位置(例如,在 点击监听器),使用将更新的getAdapterPosition() 适配器位置。
在clicklisteners
构造函数中设置ViewHolder
,可能不在onBindViewHolder
内。
例如。
public class ViewHolder implements View.OnClickListener {
//member view variables
private Button mButton;
public ViewHolder(View v) {
//findByViewId calls
super(v);
mButton = (Button) v.findViewById(R.id.button);
mButton.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.button:
int position = getAdapterPosition();
//do stuff
break;
}
}