web-dev-qa-db-ja.com

Android Room:更新挿入のLiveDataコールバック?

Simple DAO CRUD関数を含む

FeedEntryDAO.Java

@Dao
public interface FeedEntryDAO {

  @Query("SELECT * FROM feedEntrys")
  LiveData<List<FeedEntry>> getAll();

  @Query("SELECT * FROM feedEntrys WHERE uid = :uid LIMIT 1")
  LiveData<FeedEntry> findByUid(int uid);

  @Insert
  void insertAll(FeedEntry... feedEntries);

  @Delete
  void delete(FeedEntry feedEntry);

  @Update
  int update(FeedEntry feedEntry);

}

selectの場合、LiveDataタイプを返してもかまいません。

アクティビティ内のコードは選択に適しています

viewModel.getFeedEntrys().observe(this,entries -> {...});

ただし、データを挿入、更新、削除しようとすると。コードは少しいようで、毎回asynctaskを作成します。

new AsyncTask<FeedEntry, Void, Void>() {
                @Override
                protected Void doInBackground(FeedEntry... feedEntries) {
                  viewModel.update(feedEntries[0]);
                  return null;
                }
}.execute(feedEntry);

私はそれについて2つの質問があります:

  1. LiveDataを使用して、削除、挿入、更新機能をラップできますか?
  2. 削除、挿入、更新のためにそのようなasynctaskクラスを維持するより良い方法は?

提案やアドバイスに感謝します。ありがとうございました。

19
Long Ranger
  1. LiveDataを使用して、削除、挿入、更新の呼び出しをラップできますか?

いいえ、できません。 issue への回答を書きました。その理由は、LiveDataが変更の通知に使用されるためです。挿入、更新、削除は変更をトリガーしません。削除された行、挿入されたID、または影響を受けた行を返します。恐ろしく見えても、LiveDataを自分のものに巻き付けないことは理にかなっています。とにかく、呼び出しの周りにSingleのようなものを置いて、操作をRX-Java操作でトリガーして操作できるようにすることは理にかなっています。

これらの呼び出しをトリガーする場合は、一部またはすべてのデータを更新、挿入、または削除したことをLiveData onecに通知する選択クエリを確認します。

  1. 削除、挿入、更新のためにそのようなasynctaskクラスを維持するより良い方法は?

あなたの例を見ると、(Model/View /)ViewModel-Patternを誤用しているように見えます。ビューでリポジトリにアクセスしないでください。サンプルに表示されないため、これを実行しているかどうかはわかりません。とにかく、LiveDataを観察して結果を取得した後、AsyncTaskでviewModel内のデータの更新をラップする必要はありません。つまり、あなたは常に世話をする必要があることを意味します

a)ビュー<->ビューモデル<->リポジトリであり、ビュー<->リポジトリおよびビュー<->ビューモデルではありません

そして

b)不要なスレッドを使用しようとしないでください。デフォルトでバックグラウンドスレッド(@WorkerThread)でLiveDataを監視し(@MainThreadアノテーションが付いていない場合)、ui-thread(@MainThread)で値を取得します。

5
Emanuel S

2番目の質問には、 AsyncTask ;に代わるもう1つの代替手段があります。 Java Executor を使用しているため、すべてのCRUD操作でExecutorの複数のインスタンスの代わりにAsyncTaskの単一のインスタンスを使用できます。

デモの例

public class Repository {

    private static Repository instance;
    private MyDatabase mDatabase;
    private Executor mExecutor = Executors.newSingleThreadExecutor();

    private Repository(Application application) {
        mDatabase = MyDatabase.getInstance(application.getApplicationContext());
    }

    public static Repository getInstance(Application application) {
        if (instance == null) {
            instance = new Repository(application);
        }
        return instance;
    }


    public void insert(final MyModel model) {

        mExecutor.execute(new Runnable() {
            @Override
            public void run() {
                mDatabase.getMyModelDAO().insert(model);
            }
        });
    }

    public void update(final MyModel model) {
        mExecutor.execute(new Runnable() {
            @Override
            public void run() {
                mDatabase.getMyModelDAO().update(model);
            }
        });
    }

    public void delete(final MyModel model) {
        mExecutor.execute(new Runnable() {
            @Override
            public void run() {
                mDatabase.getMyModelDAO().delete(model);
            }
        });
    }

}
1
Zain

抽象クラスでも@Dao注釈を使用できます。

  1. 抽象メソッド@Insert insert(entities)と、その_いAsyncTaskジョブを実行する具象メソッドinsert(entities, callback)を含む抽象_@Dao BaseDao_クラスを作成し、抽象@Insert insert(entities) on onBackgroundおよびコールバックonPostExecute
  2. FeedEntryDAOも抽象拡張BaseDaoと_@Query_メソッドを抽象化します。

Kotlinでの結果の使用法は非常にきれいです:

_database.entityDao().insert(entities) { ids ->
    // success
}
_
1
Allan Veloso

データが変更されたときにアプリのUIが自動的に更新されるようにするには、クエリメソッドの説明でLiveData型の戻り値を使用します。データベースが更新されると、RoomはLiveDataを更新するために必要なすべてのコードを生成します。

@Dao
interface MyDao {
    @Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
    fun loadUsersFromRegionsSync(regions: List<String>): LiveData<List<User>>
}

注:バージョン1.0では、Roomはクエリでアクセスされたテーブルのリストを使用して、LiveDataのインスタンスを更新するかどうかを決定します。

0
Malwinder Singh