Неправильный порядок расположения элементов после удаления из RecyclerView. Но после перезапуска acitivty порядок верный. В чём проблема?
Я прикреплю картинки своего RecyclerView для наглядности. На 1ом фото первоначальный вид RecyclerView, на 2ом я удалил ПЕРВЫЕ ДВА элемента, но вместо них, удалились те которые с конца идут. На 3ем фото, я перезапустил activity с RecyclerView и теперь отображается как надо. Что это? Код приводится после фотографий. Помогите пожалуйста!
Код адаптера ресайкла:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.
RecyclerViewViewHolder> {
public static int adapterPosition;
private Context context;
private EntriesCursorAdapter cursorAdapter;
public static RecyclerViewViewHolder viewHolder;
public RecyclerViewAdapter(Context context, EntriesCursorAdapter cursorAdapter) {
this.context = context;
this.cursorAdapter = cursorAdapter;
}
public static class RecyclerViewViewHolder extends RecyclerView.ViewHolder {
TextView titleTextView;
TextView textTextView;
ImageButton deleteImageButton;
public RecyclerViewViewHolder(View itemView) {
super(itemView);
titleTextView = itemView.findViewById(R.id.titleTextView);
textTextView = itemView.findViewById(R.id.textTextView);
deleteImageButton = itemView.findViewById(R.id.deleteImageButton);
}
}
@Override
public RecyclerViewViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = cursorAdapter.newView(parent.getContext(), cursorAdapter.getCursor(), parent);
viewHolder = new RecyclerViewViewHolder(v);
v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), MainActivity.class);
Log.i("view.getId()", String.valueOf(view.getId()));
Uri currentEntryUri = ContentUris
.withAppendedId(Entry.CONTENT_URI, view.getId());
intent.setData(currentEntryUri);
view.getContext().startActivity(intent);
}
});
return viewHolder;
}
@Override
public void onBindViewHolder(RecyclerViewViewHolder holder, int position) {
Log.i("intPosition", String.valueOf(position));
cursorAdapter.getCursor().moveToPosition(position);
cursorAdapter.bindView(holder.itemView, context, cursorAdapter.getCursor());
holder.deleteImageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
adapterPosition = holder.getAdapterPosition(); // начинается с 0
long id = MainActivity.arrayListIdElem.get(adapterPosition); // если 0, то id 1
Log.i("positionRecycler", String.valueOf(adapterPosition));
Log.i("idElem", String.valueOf(id));
showDeleteEntryDialog(id);
}
});
}
@SuppressLint("LongLogTag")
@Override
public int getItemCount() {
Log.i("cursorAdapter.getCount()", String.valueOf(cursorAdapter.getCount()));
return cursorAdapter.getCount();
}
private void showDeleteEntryDialog(long id) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage("Вы хотите удалить подсказку?");
builder.setPositiveButton("Удалить",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Uri currentEntryUri = ContentUris
.withAppendedId(Entry.CONTENT_URI, id);
Log.i("currentUri_new", String.valueOf(currentEntryUri));
deleteEntry(currentEntryUri);
dialogInterface.dismiss();
}
});
builder.setNegativeButton("Отмена",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
if (dialogInterface != null) {
dialogInterface.dismiss();
}
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
private void deleteEntry(Uri currentEntryUri) {
if (currentEntryUri != null) {
int rowsDeleted = context.getContentResolver().delete(currentEntryUri,
null, null);
if (rowsDeleted == 0) {
Toast.makeText(context, "Не получилось удалить", Toast.LENGTH_SHORT).show();
} else {
MainActivity.arrayListIdElem.remove(adapterPosition);
// Сохранение обновлённого состояния arrayList
SharedPreferences sharedPreferences = context.getSharedPreferences(
"shared_prefernces", MODE_PRIVATE);
MainActivity.saveArrayList(sharedPreferences);
Toast.makeText(context, "Подсказка удалена", Toast.LENGTH_SHORT).show();
}
Log.i("currentUri", String.valueOf(currentEntryUri));
}
}
}
Фрагмент кода из MainActivity, где происходит сохранение данных.
public void saveTextAndShowInputDialog(View view) {
String text = editText.getText().toString().trim();
if (TextUtils.isEmpty(text)) {
Toast.makeText(this, "Заполните поле подсказки", Toast.LENGTH_SHORT).show();
return;
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
final EditText input = new EditText(this);
builder.setView(input);
builder.setTitle("Название подсказки");
builder.setPositiveButton("Сохранить",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
title = input.getText().toString();
dialogInterface.dismiss();
save();
}
});
builder.setNegativeButton("Отмена",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
private void save() {
/* Сохранение подсказки в БД. Либо обновление, если uri записи не равен null. */
String text = editText.getText().toString().trim();
String title_trim = title;
if (TextUtils.isEmpty(title_trim)) {
Toast.makeText(this, "Заполните поле названия", Toast.LENGTH_SHORT).show();
return;
}
ContentValues contentValues = new ContentValues();
contentValues.put(Entry.KEY_TITLE, title_trim);
contentValues.put(Entry.KEY_TEXT, text);
if (currentEntryUri == null) {
// Добавляем новую запись.
ContentResolver contentResolver = getContentResolver();
Uri uri = contentResolver.insert(Entry.CONTENT_URI, contentValues);
if (uri == null) {
Toast.makeText(this, "Insertion of data in the table failed for " + uri,
Toast.LENGTH_LONG).show();
} else {
Log.i("save_uri", String.valueOf(uri));
Toast.makeText(this, "Подсказка сохранена", Toast.LENGTH_SHORT).show();
}
} else {
// Обновляем существующую запись.
int rowsChanged = getContentResolver().update(currentEntryUri, contentValues,
null, null);
if (rowsChanged == 0) {
Toast.makeText(this, "Произошла ошибка при обновлении",
Toast.LENGTH_SHORT).show();
return;
} else {
Toast.makeText(this, "Подсказка обновлена", Toast.LENGTH_SHORT).show();
}
}
}
public static void saveArrayList(SharedPreferences sharedPreferences) {
/* Сохранение ArrayList с неизменными id каждого элемента ресайкла. */
SharedPreferences.Editor editor = sharedPreferences.edit();
Gson gson = new Gson();
String json = gson.toJson(arrayListIdElem);
editor.putString("arrayList", json);
editor.apply();
}
public void loadArrayList() {
/* Чтение данных(ArrayList) из SharedPrefences. */
SharedPreferences sharedPreferences = getSharedPreferences("shared_prefernces",
MODE_PRIVATE);
Gson gson = new Gson();
String json = sharedPreferences.getString("arrayList", null);
Type type = new TypeToken<ArrayList<Long>>() {}.getType();
arrayListIdElem = gson.fromJson(json, type);
if (arrayListIdElem == null) {
arrayListIdElem = new ArrayList<>();
Toast.makeText(this, String.valueOf(arrayListIdElem), Toast.LENGTH_SHORT).show();
}
}
}
Код ContentProvider:
public class ContentProvider extends ContentProvider {
SchoolDBOpenHelper SchoolDBOpenHelper;
private static final int ENTRIES = 111;
private static final int ENTRY_ID = 222;
private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
uriMatcher.addURI(CheatingSchoolContract.AUTHORITY,
CheatingSchoolContract.PATH_ENTRIES, ENTRIES);
uriMatcher.addURI(CheatingSchoolContract.AUTHORITY,
CheatingSchoolContract.PATH_ENTRIES + "/#", ENTRY_ID);
}
@Override
public boolean onCreate() {
SchoolDBOpenHelper = new SchoolDBOpenHelper(getContext());
/* SQLiteDatabase db = SchoolDBOpenHelper.getWritableDatabase();
db.delete("entries", null, null);
MainActivity.arrayListIdElem.clear();
// Сохранение
SharedPreferences sharedPreferences = getContext().getSharedPreferences(
"shared_prefernces", MODE_PRIVATE);
MainActivity.saveArrayList(sharedPreferences);*/
return true;
}
@Override
public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
SQLiteDatabase db = SchoolDBOpenHelper.getReadableDatabase();
Cursor cursor;
int match = uriMatcher.match(uri);
switch (match) {
case ENTRIES:
cursor = db.query(Entry.TABLE_NAME, strings,
s, strings1, null, null, s1);
break;
case ENTRY_ID:
s = Entry.KEY_ID + "=?";
strings1 = new String[] {String.valueOf(ContentUris.parseId(uri))};
cursor = db.query(Entry.TABLE_NAME, strings,
s, strings1, null, null, s1);
break;
default:
throw new IllegalArgumentException("Can't query incorrect uri " + uri);
}
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
@Override
public String getType(Uri uri) {
return null;
}
@SuppressLint("LongLogTag")
@Override
public Uri insert(Uri uri, ContentValues values) {
// Валидация данных.
String title = values.getAsString(Entry.KEY_TITLE);
if (title == null) {
throw new IllegalArgumentException("Заполни название");
}
String text = values.getAsString(Entry.KEY_TEXT);
if (text == null) {
throw new IllegalArgumentException("Заполни поле для подсказки");
}
SQLiteDatabase db = SchoolDBOpenHelper.getWritableDatabase();
int match = uriMatcher.match(uri);
switch (match) {
case ENTRIES:
long id = db.insert(Entry.TABLE_NAME, null, values);
if (id == -1) {
Log.e("methodInsert", "Insertion of data in the table failed for " + uri);
return null;
}
MainActivity.arrayListIdElem.add(id);
// Сохранение
SharedPreferences sharedPreferences = getContext().getSharedPreferences(
"shared_prefernces", MODE_PRIVATE);
MainActivity.saveArrayList(sharedPreferences);
getContext().getContentResolver().notifyChange(uri, null);
Log.i("create long id in insert()", String.valueOf(id));
return ContentUris.withAppendedId(uri, id);
default:
throw new IllegalArgumentException("Insertion of data in the table failed for" +
uri);
}
}
@Override
public int delete(Uri uri, String s, String[] strings) {
SQLiteDatabase db = SchoolDBOpenHelper.getWritableDatabase();
int rowsDeleted;
int match = uriMatcher.match(uri);
switch (match) {
case ENTRIES:
rowsDeleted = db.delete(Entry.TABLE_NAME, s, strings);
break;
case ENTRY_ID:
s = Entry.KEY_ID + "=?";
strings = new String[] {String.valueOf(ContentUris.parseId(uri))};
rowsDeleted = db.delete(Entry.TABLE_NAME, s, strings);
break;
default:
throw new IllegalArgumentException("Can't delete this URI " + uri);
}
if (rowsDeleted != 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
for (String str : strings) {
Log.i("stringsId", str); ////////////////
}
return rowsDeleted;
}
@Override
public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
return 0;
}
}
Код CursorAdapter
public class EntriesCursorAdapter extends CursorAdapter {
public EntriesCursorAdapter(Context context, Cursor c) {
super(context, c, 0);
}
@SuppressLint("Range")
@Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
return LayoutInflater.from(context).inflate(
R.layout.recycler_view_item, viewGroup, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
String title = cursor.getString(cursor.getColumnIndexOrThrow(Entry.KEY_TITLE));
String text = cursor.getString(cursor.getColumnIndexOrThrow(Entry.KEY_TEXT));
title = title.length() > 23 ? title.substring(0, 23)+"..." : title;
text = text.length() > 75 ? text.substring(0, 75)+"..." : text;
RecyclerViewAdapter.viewHolder.titleTextView.setText(title);
RecyclerViewAdapter.viewHolder.textTextView.setText(text);
}
}
Код Activity с RecyclerView
public class SavedActivity extends AppCompatActivity
implements LoaderManager.LoaderCallbacks<Cursor> {
private static final int ENTRY_LOADER = 123;
private RecyclerView dataRecyclerView;
private RecyclerView.Adapter adapter;
private RecyclerView.LayoutManager layoutManager;
EntriesCursorAdapter entriesCursorAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_saved);
ActionBar actionBar = this.getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
dataRecyclerView = findViewById(R.id.dataRecyclerView);
entriesCursorAdapter = new EntriesCursorAdapter(this, null);
dataRecyclerView.hasFixedSize();
adapter = new RecyclerViewAdapter(this, entriesCursorAdapter);
layoutManager = new LinearLayoutManager(this);
dataRecyclerView.setAdapter(adapter);
dataRecyclerView.setLayoutManager(layoutManager);
getSupportLoaderManager().initLoader(ENTRY_LOADER, null, this);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
NavUtils.navigateUpFromSameTask(this);
}
return super.onOptionsItemSelected(item);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
/* Два последующих метода отвечают за вывод данных из бд. */
String[] projection = {
Entry.KEY_ID,
Entry.KEY_TITLE,
Entry.KEY_TEXT
};
CursorLoader cursorLoader = new CursorLoader(this,
Entry.CONTENT_URI, projection,
null,
null,
null);
return cursorLoader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
entriesCursorAdapter.swapCursor(data);
adapter.notifyDataSetChanged(); // Вот
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
entriesCursorAdapter.swapCursor(null);
adapter.notifyDataSetChanged(); // И вот
}
}


