Обновление и удаление библиотеки ROOM ничего не изменит - PullRequest
1 голос
/ 06 октября 2019

Я программирую небольшое приложение и использую для этого место. Оболочка SQLite. Поскольку я получил работающий код, есть некоторые функции, которые они не работают. Также документация кажется очень неполной или, скорее, неправильной в некоторых моментах. Например, аннотации dao @Update и @Delete. Я медленно путаюсь с использованием этой инфраструктуры и думаю вернуться к использованию SQLite API вместо этого. Что вы думаете о комнате?

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

Как и прежде, моя сущность и Дао. Он должен представлять собой аудиофайл.

@Entity(tableName = "audiofile")
public class AudioFile
{
    @PrimaryKey(autoGenerate = true)
    private long id;

    @ColumnInfo(name = "title")
    private String title;

    @ColumnInfo(name = "artist")
    private String artist;

    @ColumnInfo(name = "path")
    private String path;

    @ColumnInfo(name = "duration")
    private long duration;

@Dao
public interface AudioFileDao
{
    @Query("SELECT * FROM audiofile WHERE title LIKE :title")
    AudioFile getAudioFile(String title);

    @Query("SELECT * FROM audiofile")
    List<AudioFile> getAll();

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void initAudioFiles(AudioFile... audioFiles);

    @Update
    void updateAudioFile(AudioFile... audioFiles);

//        @Query("DELETE FROM audiofile WHERE id = :audioFileId")
    @Delete
    void deleteAudioFile(AudioFile audioFile);

    @Insert
    void insertAll(AudioFile... audioFiles);

    @Insert
    long insertAudioFile(AudioFile audioFile);
}

Это обычный менеджер базы данных.

@Database(entities = {AudioFile.class}, version = 1)
public abstract class DbManager extends RoomDatabase
{

    private static DbManager INSTANCE;

    public abstract AudioFile.AudioFileDao audioFileDao();

    public static DbManager getDbManager(Context ctx){
        if (INSTANCE == null){
            INSTANCE = Room.databaseBuilder(ctx.getApplicationContext(), DbManager.class, "playlist").build();
        }
        return INSTANCE;
    }

    public static void destroyInstance(){
        INSTANCE = null;
    }
}

Ааа, а вот и мой тест, который вызывает все мои опасения:

@RunWith(JUnit4.class)
public class DbManagerAndroidTest
{
    private AudioFile.AudioFileDao audioFileDao;
    private DbManager db;

    @Before
    public void createDb()
    {
        Context ctx = InstrumentationRegistry.getInstrumentation().getContext();

        db = Room.inMemoryDatabaseBuilder(ctx, DbManager.class).build();
        audioFileDao = db.audioFileDao();
    }

    /**
     * Test CRUD
     */
    @Test
    public void writeAndRead()
    {
        AudioFile audioFile = new AudioFile.Builder("title")
            .withArtist("artist")
            .withDuration(5)
            .withPath("/this/is/path")
            .build();

        audioFileDao.insertAudioFile(audioFile);
        assertTrue(db.audioFileDao().getAll().size() > 0);
        assertEquals("title", db.audioFileDao().getAll().get(0).getTitle());

        audioFile.setArtist("yo-mama");
        //It won´t update
        audioFileDao.updateAudioFile(audioFile);

        assertEquals("yo-mama", audioFileDao.getAudioFile("title").getArtist());
        //It won´t delete
        audioFileDao.deleteAudioFile(audioFile);
        assertEquals(0, audioFileDao.getAll().size());
    }

    @After
    public void tearDown(){
        db.clearAllTables();
        db.close();
    }
}

Заранее спасибо за помощь. Эта вещь сводит меня с ума.

1 Ответ

0 голосов
/ 06 октября 2019

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

Я считаю, что ваша проблема заключается в том, что при вставке AudioFile идентификатор не устанавливается и, следовательно, 0 вобъект AudioFile audioFile. Тем не менее, после вставки идентификатор будет автоматически сгенерирован и не будет 0, скорее всего, это будет количество объектов AudioFile, вставленных за некоторое время + 1.

Без установки id на затемиспользовать тот же объект AudioFile для обновления / удаления будет пытаться обновить удаление, используя идентификатор 0 . Такой строки не будет.

Исправление при условии, что для AudioFile существует метод setId , но при условии отсутствия обработки неудачной вставки можно использовать: -

audioFile.setId(audioFileDao.insertAudioFile(audioFile));

Исправление, которое может обработать неудачную вставку, которая не привела к исключению, может быть: -

long insertedId = audioFileDao.insertAudioFile(audioFile);
if (insertedId > 0) {
    audioFile.setId(insertedId);
} else {
    //......... handle not inserted
}

Пример / Демо

Следующий кодпри запуске показывает вышеприведенное (ваши Entity и Dao были скопированы как есть): -

    ...... database built
    mAudioFileDao = mAppDB.audioFileDao();

    AudioFile a = new AudioFile();
    a.setTitle("MySong");
    a.setDuration(5);
    a.setArtist("Fred");
    a.setPath("/thepath");

    logAudioFile(a,"Before Insert into DB");
    long currentId = mAudioFileDao.insertAudioFile(a); //<<<<<<<<<< INSERT INTO DB
    logAudioFile(a,"Immediately after Insert. ID returned from insert is " + currentId);
    a.setId(currentId); //<<<<<<<<<< SET the the id of the AudioFile object a
    logAudioFile(a,"After setting the ID to " + currentId);
    mAudioFileDao.updateAudioFile(a);
    List<AudioFile> audioFileList = mAudioFileDao.getAll();
    for (AudioFile af: audioFileList) {
        logAudioFile(af,"Extracted from DB");
    }
    mAudioFileDao.deleteAudioFile(a);
    Log.d("AUDIOFILEINFO","Attempt to delete Audio File undertaken");
    audioFileList = mAudioFileDao.getAll();
    for (AudioFile af: audioFileList) {
        logAudioFile(af,"After deletion");
    }

logAudioFile метод: -

private void logAudioFile(AudioFile a, String extra) {
    Log.d(
            "AUDIOFILEINFO",
            "Title is " + a.getTitle() +
                    " ID is " + a.getId() +
                    "\n\tExtra Info is " + extra
    );
}

Результат (журнал сверху): -

2019-10-06 11:03:39.757 D/AUDIOFILEINFO: Title is MySong ID is 0
        Extra Info is Before Insert into DB
2019-10-06 11:03:39.808 D/AUDIOFILEINFO: Title is MySong ID is 0
        Extra Info is Immediately after Insert. ID returned from insert is 1
2019-10-06 11:03:39.808 D/AUDIOFILEINFO: Title is MySong ID is 1
        Extra Info is After setting the ID to 1
2019-10-06 11:03:39.829 D/AUDIOFILEINFO: Title is MySong ID is 1
        Extra Info is Extracted from DB
2019-10-06 11:03:39.831 D/AUDIOFILEINFO: Attempt to delete Audio File undertaken

Что вы думаете о комнате?

Это вопрос мнений, поэтому не по теме.

...