База данных комнаты неправильно обновляет идентификатор при добавлении или удалении данных - PullRequest
1 голос
/ 21 мая 2019

Я создаю приложение, которое позволяет пользователю хранить имена пользователей и пароли. Пользователь нажимает на FAB, и начинается действие AddEditEntry.java. Пользователь вводит имя пользователя, вводит или генерирует пароль, вводит подсказку и нажимает кнопку Сохранить. Новые данные представлены в списке в Mainactivity.java. Если пользователь решает редактировать запись, все, что ему нужно сделать - это долго щелкнуть по элементу, и тот же класс AddEditEntry.java начинается с предыдущих данных в полях. Затем пользователь может изменить эти данные и нажать «Сохранить», чтобы обновить запись. На панели действий также есть кнопка для удаления всех записей, или пользователь может провести запись влево / вправо, чтобы удалить ее из базы данных.

Вместо этого вот что происходит:

  • Пользователь может успешно добавлять новые записи.
  • При длинном щелчке AddEditEntry.java успешно наполняет поля предыдущими данными
  • Когда пользователь удаляет запись (с помощью пролистывания влево / вправо или нажатия кнопки удаления всех), новая запись не начинается со значения ID, равного 1 и далее. Запись начинается с того места, где остановилась предыдущая запись. Поэтому, если я удаляю запись с идентификатором = 1, идентификатор новой записи = 2.
  • Еще хуже, когда я нажимаю кнопку сохранения, чтобы обновить запись, идентификатор становится -1. И когда это происходит, значения для записи вообще не существуют, потому что я проверяю их с помощью сообщений Toast в каждом состоянии. Таким образом, обновление не выполняется, и запись остается прежней.

Приложение построено на основе архитектуры MVVM, поэтому у меня есть классы (сущность, DAO, база данных, репозиторий, модель представления), а также необходимый класс адаптера. Я буду публиковать только соответствующий код, чтобы избежать беспорядка в максимально возможной степени. Я могу добавить больше кода для каждого запроса.

MainActivity.java:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        //Sends the existing entry for editing
        adapter.setOnItemLongClickListener(new RecyclerViewAdapter.OnItemLongClickListener() {
            @Override
            public void onItemLongClick(Entries entries) {
                Intent intent = new Intent(MainActivity.this, AddEditEntry.class);

                intent.putExtra(AddEditEntry.EXTRA_USERNAME, entries.getUsername());
                intent.putExtra(AddEditEntry.EXTRA_HINT, entries.getHint());
                intent.putExtra(AddEditEntry.EXTRA_PASSWORD, entries.getPassword());
                intent.putExtra(AddEditEntry.EXTRA_ID, entries.getId());
                startActivityForResult(intent, EDIT_ENTRY_REQUEST);

                Toast.makeText(MainActivity.this, entries.getUsername(), Toast.LENGTH_SHORT).show();
                Toast.makeText(MainActivity.this, entries.getHint(), Toast.LENGTH_SHORT).show();
                Toast.makeText(MainActivity.this, entries.getPassword(), Toast.LENGTH_SHORT).show();
                Toast.makeText(MainActivity.this, String.valueOf(entries.getId()), Toast.LENGTH_SHORT).show();
            }
        });
    }
...
    //The onActivityResult retrieves the result when the user adds
    // or edits an entry by checking for the specific request code
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if(requestCode == ADD_ENTRY_REQUEST && resultCode == RESULT_OK){
            String username = Objects.requireNonNull(data).getStringExtra(AddEditEntry.EXTRA_USERNAME);
            String password = Objects.requireNonNull(data).getStringExtra(AddEditEntry.EXTRA_PASSWORD);
            String hint = Objects.requireNonNull(data).getStringExtra(AddEditEntry.EXTRA_HINT);

            Entries entry = new Entries(username, hint, password);
            viewModel.insert(entry);

            Toast.makeText(this, "Entry added!", Toast.LENGTH_SHORT).show();

        }else if(requestCode == EDIT_ENTRY_REQUEST && resultCode == RESULT_OK){
            int id = getIntent().getIntExtra(AddEditEntry.EXTRA_ID, -1);
            String username = Objects.requireNonNull(data).getStringExtra(AddEditEntry.EXTRA_USERNAME);
            String password = Objects.requireNonNull(data).getStringExtra(AddEditEntry.EXTRA_PASSWORD);
            String hint = Objects.requireNonNull(data).getStringExtra(AddEditEntry.EXTRA_HINT);

            if (id == -1){Toast.makeText(this, "Something went wrong", Toast.LENGTH_SHORT).show();}

            Entries entry = new Entries(username, hint, password);
            entry.setId(id);
            viewModel.update(entry);

            Toast.makeText(this, String.valueOf(id), Toast.LENGTH_SHORT).show();
            Toast.makeText(this, username, Toast.LENGTH_SHORT).show();
            Toast.makeText(this, password, Toast.LENGTH_SHORT).show();
            Toast.makeText(this, hint, Toast.LENGTH_SHORT).show();

            Toast.makeText(this, "Entry updated", Toast.LENGTH_SHORT).show();

        }else{Toast.makeText(this, "Entry not added!", Toast.LENGTH_SHORT).show();}
    }

AddEditEntry.java

public class AddEditEntry extends AppCompatActivity {

    public static final String EXTRA_USERNAME = "com.ozbek.cryptpass.EXTRA_USERNAME";
    public static final String EXTRA_HINT = "com.ozbek.cryptpass.EXTRA_HINT";
    public static final String EXTRA_PASSWORD = "com.ozbek.cryptpass.EXTRA_PASSWORD";
    public static final String EXTRA_ID = "com.ozbek.cryptpass.EXTRA_ID";
    public static final int EDIT_ENTRY_REQUEST = 3;

    ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...

        final Intent intent = getIntent();
        // If the ID was passed, gets the extras for editing
        if(intent.hasExtra(EXTRA_ID)){
            setTitle("Edit Entry");
            saveEntry.setText("Update Entry");
            usernameEditText.setText(getIntent().getStringExtra(EXTRA_USERNAME));
            passwordEditText.setText(getIntent().getStringExtra(EXTRA_PASSWORD));
            hintEditText.setText(getIntent().getStringExtra(EXTRA_HINT));
            int id = getIntent().getIntExtra(EXTRA_ID, -1);

            Toast.makeText(this, "Info Received!!!", Toast.LENGTH_SHORT).show();
            Toast.makeText(this, getIntent().getStringExtra(EXTRA_USERNAME), Toast.LENGTH_SHORT).show();
            Toast.makeText(this, getIntent().getStringExtra(EXTRA_PASSWORD), Toast.LENGTH_SHORT).show();
            Toast.makeText(this, getIntent().getStringExtra(EXTRA_HINT), Toast.LENGTH_SHORT).show();
            Toast.makeText(this, String.valueOf(id), Toast.LENGTH_SHORT).show();
        }

        else{setTitle("Add Entry");}

        generatePassword.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {passwordEditText.setText(generatedPassword());}});

        saveEntry.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent data = new Intent();
                data.putExtra(EXTRA_USERNAME, usernameEditText.getText().toString());
                data.putExtra(EXTRA_HINT, hintEditText.getText().toString());
                data.putExtra(EXTRA_PASSWORD, passwordEditText.getText().toString());

                setResult(RESULT_OK, data);
                finish();
            }
        });
    }

    ...
}

EntryViewModel.java

public class EntryViewModel extends AndroidViewModel {
    private EntryRepository repository;
    private LiveData<List<Entries>> allEntries;


    public EntryViewModel(@NonNull Application application) {
        super(application);
        repository = new EntryRepository(application);
        allEntries = repository.getAllEntries();
    }

    public void insert(Entries entries){repository.insert(entries);}

    public void update(Entries entries){repository.update(entries);}

    public void delete(Entries entries){repository.delete(entries);}

    public void deleteAll(){repository.deleteAllEntries();}

    public LiveData<List<Entries>> getAllEntries() {return allEntries;}
}

Entries.java

@Entity(tableName = "entries_table")
public class Entries {
    @PrimaryKey(autoGenerate = true)
    private int id;

    private String username, hint, password;

    public Entries(String username, String hint, String password){
        this.username = username;
        this.hint = hint;
        this.password = password;
    }

    public Entries(){}

    public int getId() {return id;}

    public void setId(int id) {this.id = id;}

    public String getUsername() {return username;}

    public void setUsername(String username) {this.username = username;}

    public String getHint() {return hint;}

    public void setHint(String hint) {this.hint = hint;}

    public String getPassword() {return password;}

    public void setPassword(String password) {this.password = password;}
}

Вот полный исходный код

Ответы [ 2 ]

1 голос
/ 23 мая 2019

Просто добавьте эти исправления.

В onClick() вашего saveEntry (я полагаю, это кнопка) в AddEditEntry.java, измените его на:

    saveEntry.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent data = new Intent();
            data.putExtra(EXTRA_USERNAME, usernameEditText.getText().toString());
            data.putExtra(EXTRA_HINT, hintEditText.getText().toString());
            data.putExtra(EXTRA_PASSWORD, passwordEditText.getText().toString());

            //You were missing these 2 lines
            int id  = getIntent().getIntExtra(EXTRA_ID, -1);
            if(id != -1){data.putExtra(EXTRA_ID, id);}

            setResult(RESULT_OK, data);
            finish();
        }
    });

И в методе onActivityResult внутри вашего MainActivity.java сделайте это быстрое исправление:

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if(requestCode == ADD_ENTRY_REQUEST && resultCode == RESULT_OK){
        ...

    }else if(requestCode == EDIT_ENTRY_REQUEST && resultCode == RESULT_OK){
        int id = Objects.requireNonNull(data).getIntExtra(AddEditEntry.EXTRA_ID, -1);

        if (id == -1){
            Toast.makeText(this, "Something went wrong", Toast.LENGTH_SHORT).show();
            return;
        }

        ...

    }else{Toast.makeText(this, "Entry not added!", Toast.LENGTH_SHORT).show();}
}

Это должно работать после этого. Дайте мне знать, если у вас возникнут проблемы.

0 голосов
/ 22 мая 2019

Когда пользователь удаляет запись (с помощью пролистывания влево / вправо или нажатия кнопки удаления всех), новая запись не начинается со значения ID, равного 1 и далее. Запись начинается с того места, где остановилась предыдущая запись. Поэтому, если я удаляю запись с идентификатором = 1, идентификатор новой записи = 2.

Это поведение по умолчанию для автоматически сгенерированного первичного ключа. Что с ним не так?

Еще хуже, когда я нажимаю кнопку сохранения, чтобы обновить запись, идентификатор становится -1. И когда это происходит, значения для записи вообще не существуют, потому что я проверяю их с помощью сообщений Toast в каждом состоянии. Таким образом, обновление не выполняется, и запись остается прежней.

Я не прочитал весь код, но это похоже на проблему конфликта. Попробуйте добавить стратегию замены к своим запросам.

@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(Entries entries);

@Update(onConflict = OnConflictStrategy.REPLACE)
void update(Entries entries);
...