ウィジェットクラス内のRoomDBにアクセスして、保存されているデータに従ってウィジェットを更新したかったのです。
ここでの問題は、ViewModelProviderが動作するためにフラグメントまたはアクティビティを必要とすることです。
ViewModelProviders.of(fragment).get(YourViewModel.class);
これはアプリウィジェットクラスでは利用できないので、どうすればよいですか?
RemoteViewsService を使用してウィジェットUIにデータを入力する場合、AppWidgetProviderのonDataSetChanged()
メソッドではなくonUpdate()
メソッドにDAOクエリを含めることで、AsyncTaskの使用を回避できます。 。 onDataSetChanged()
ドキュメント に記載されているように、
...高価なタスクは、このメソッド内で同期して安全に実行できます。暫定的に、古いデータがウィジェット内に表示されます。
ここでの他の利点は、アプリのViewModelオブザーバーのAppWidgetManager.notifyAppWidgetViewDataChanged()
メソッドにonChanged()
の呼び出しを含めることができることです。これによりonDataSetChanged()
がトリガーされ、ウィジェットはonUpdate()
の固定間隔ではなく、Roomデータベースが変更されるたびに更新されます。
viewModelを経由せずにRoomにアクセスできます。ViewModelはMVCやMVPと同様に、MVVMアーキテクチャのコンポーネントにすぎません。ViewModelがなくてもRoomにアクセスできます。コンテキストが必要です。
久しぶりですが、この問題に出くわし、仲間のアーロン・デュニガン・アトリーのインスピレーションを受けて、何か役に立つものを追加したいと思いました。
基本的に、データベースとDaoオブジェクトの移動先を示します...さらに重要なのは、Roomクエリを呼び出すonDataSetChanged()
メソッドです。この例は、メモを取るアプリが説明するためのものであり、上記でコメントしたように、どこにもAsyncTasksは必要ありません。
public class MyWidgetRemoteViewsService extends RemoteViewsService
{
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent)
{
return new MyRemoteViewsFactory(this.getApplicationContext(), intent);
}
class MyRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory
{
private NotesDao notesDao;
private List<Note> allNotes;
MyRemoteViewsFactory(Context context, Intent intent)
{
MyDb db;
db = MyDatabase.getDatabase(context);
notesDao = db.notesDao();
}
@Override
public void onCreate() { }
@Override
public void onDataSetChanged()
{
allNotes = notesDao.getAllNotes();
}
@Override
public int getCount()
{ ...
ささ
だからここで私の自己に答える。
機能した唯一の方法は、コンテキストを使用して抽象クラスからDBインスタンスを取得し、ViewModelProvidersクラスを使用せずにバックグラウンドスレッドでDAOクエリを直接実行することです。
new AsyncTask<Context, Void, List<Data>>(){ @Override protected List<Quote> doInBackground(Context... context) { List<Data> List=null; AppDatabase db = AppDatabase.getDatabase(context[0]); List = db.DataModel().getData(); return List; } @Override protected void onPostExecute(List<Quote> List) { super.onPostExecute(List); if(List != null){ final Random random=new Random(); for (int appWidgetId : appWidgetIds) { updateAppWidget(context, appWidgetManager, appWidgetId, quoteList.get(random.nextInt(List.size()))); } } } }.execute(context); }
RoomからデータにアクセスするためにViewModelは必要ありません。どこからでもデータにアクセスできますが、データの変更が機能しないときに通知を受け取るというすばらしい機能があります。これを行うには、LiveData>ではなく単純なリストを返すメソッドをDaoオブジェクトに追加するだけです。そしてそれだけです。
正確に、あなたはそれを行うことができます..あなたはすでにバックグラウンドスレッドからこのDAOクエリを作成する必要があるので、クエリを実行するためにコンテキストをAsyncTaskに渡すことは良い解決策ですが、代わりにAsyncTaskのコンストラクタでコンテキストを渡すようにしてくださいparamsでそれを渡します。