16

最近、私は最近Googleによって導入されたAndroid Architectureを模索しています。次のように活動がこのリストにアクセス可能バックグラウンドサービスとアップデートUIからViewModelのLiveDataを更新する方法

public class MyViewModel extends ViewModel { 
    private MutableLiveData<List<User>> users; 
    public LiveData<List<User>> getUsers() { 
     if (users == null) { 
      users = new MutableLiveData<List<Users>>(); 
      loadUsers(); 
     } 
     return users; 
    } 

    private void loadUsers() { 
     // do async operation to fetch users 
    } 
} 

public class MyActivity extends AppCompatActivity { 
    public void onCreate(Bundle savedInstanceState) { 
     MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class); 
     model.getUsers().observe(this, users -> { 
      // update UI 
     }); 
    } 
} 

を私の質問は、私が最初にチェックする場所、私は非同期にデータを取得していますloadUsers()機能では、あるDocumentationから、私はこれを発見しましたそのデータのデータベース(Room)。そこにデータがない場合は、Webサーバーからデータを取得するAPI呼び出しを行います。次に、取得したデータをデータベース(ルーム)に挿入し、データに応じてUIを更新します。これを行うために推奨されるアプローチは何ですか?

loadUsers()メソッドからServiceメソッドを呼び出して開始すると、の変数をMutableLiveData<List<User>> users変数に更新するにはどうすればよいですか?

+2

まず、リポジトリがありません。あなたのViewModelは、データ読み込みタスクを行うべきではありません。それ以外の場合は、あなたの部屋を使用しているので、あなたのサービスはViewModelのLiveDataを直接更新する必要はありません。 Roomにデータを挿入するだけで、ViewModelDataはRoomにのみ接続し、Roomから更新を取得する必要があります(サービスがデータを挿入した後)。しかし、絶対的なベストアーキテクチャーについては、このページの一番下からNetworkBoundResourceクラスの実装を見てください:https://developer.android.com/topic/libraries/architecture/guide.html –

+0

提案ありがとうございました:) – CodeCameo

+0

リポジトリクラスは、ROOMまたはアンドロイドのアーキテクチャのコンポーネントを記述するオフショアのドキュメントに記載されていません – jonney

答えて

3

私はあなたがandroid architecture componentsを使用していると仮定しています。実際には、service, asynctask or handlerと呼んでどこにいてもデータを更新する必要はありません。サービスまたはasynctaskからデータを挿入できます。あなたのクラスはgetAllUsers()としてthis-

public LiveData<List<User>> getUsers() { 
     if (users == null) { 
      users = new MutableLiveData<List<Users>>(); 
      // Asynchronous call for inserting data using service or asynctask. 
      loadUsers(); 
     } 
     // Dao live data will provide you all users information if data inserted. 
     LiveData<List<User>> mUsers = mDb.userDao().getAllUsers(); 
     users.postValue(mUsers); 
     return users; 
    } 

のように見えることでしょうRoomデータベースは、それが挿入されている場所のユーザデータを提供する責任があり、LiveDataです。

Note: MVVMのようなアーキテクチャでは、リポジトリは主にローカルデータとリモートデータのチェックとプルを担当します。

+0

私は "java.lang.IllegalStateExceptionを取得しています:それ以来、メインスレッドでデータベースにアクセスすることはできません"上記のように私のdbメソッドを呼び出すには、 ? – pcj

+0

私はUI上で、データベースをバックグラウンドで更新しているevernote-jobを使用しています。しかし、 'LiveData'は更新されていません –

2

LiveDataViewModelのような新しいアーキテクチャモジュールに付随するAndroid architecture guideを見てください。彼らはこの正確な問題について深く議論します。

これらの例では、サービスには入れません。彼らが "リポジトリ"モジュールとRetrofitを使って解決する方法を見てみましょう。私は非同期にデータをフェッチしていますloadUsers()関数内の一番下の歯先エラーを報告し、ネットワークの状態を伝えるなど、より完全な例を含む、など

5

... ... 私がサービスを開始した場合loadUsers()メソッドからAPIを呼び出します。 サービスから MutableLiveData> users変数をどのように更新できますか?

アプリ(むしろsetValueより)バックグラウンドスレッド、postValueにユーザデータをフェッチしている場合には有用であろう。

loadDataメソッドには、MutableLiveDataの「users」オブジェクトへの参照があります。また、loadDataメソッドは、どこかの新しいユーザーデータ(たとえば、リポジトリ)を取得します。

実行がバックグラウンドスレッド上にある場合、MutableLiveData.postValue()はMutableLiveDataオブジェクトのオブザーバーの外側で更新されます。

たぶん、このような何か:

private MutableLiveData<List<User>> users; 

. 
. 
. 

private void loadUsers() { 
    // do async operation to fetch users 
    ExecutorService service = Executors.newSingleThreadExecutor(); 
    service.submit(new Runnable() { 
     @Override 
     public void run() { 
      // on background thread, obtain a fresh list of users 
      List<String> freshUserList = aRepositorySomewhere.getUsers(); 

      // now that you have the fresh user data in freshUserList, 
      // make it available to outside observers of the "users" 
      // MutableLiveData object 
      users.postValue(freshUserList);   
     } 
    }); 

} 
+0

リポジトリの' getUsers() 'メソッドは、async(サービスを開始するかもしれないし、asynctaskを起動しているかもしれない)のデータに対してapiを呼び出すかもしれません。 – CodeCameo

+0

おそらく、LiveDataオブジェクトを引数として受け取る可能性があります。 (repository.getUsers(users)のようなもの)。次に、リポジトリメソッドはusers.postValue自体を呼び出します。その場合、loadUsersメソッドはバックグラウンドスレッドを必要としません。 –

20

してくださいは、ライブデータのpostValue(..)バックグラウンドスレッドからメソッドを使用します。

private void loadUsers() { 
    // do async operation to fetch users and use postValue() method 
    users.postValue(listOfData) 
} 
+2

通知するには、postValue()はLiveDataでは保護されていますが、MutableLiveData –

関連する問題