Неправильный порядок расположения элементов после удаления из RecyclerView. Но после перезапуска acitivty порядок верный. В чём проблема?

Я прикреплю картинки своего RecyclerView для наглядности. На 1ом фото первоначальный вид RecyclerView, на 2ом я удалил ПЕРВЫЕ ДВА элемента, но вместо них, удалились те которые с конца идут. На 3ем фото, я перезапустил activity с RecyclerView и теперь отображается как надо. Что это? Код приводится после фотографий. Помогите пожалуйста!

Первоначальный вид Recycler

введите сюда описание изображения

Код адаптера ресайкла:


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(); // И вот 
    }
}

Ответы (0 шт):