web-dev-qa-db-ja.com

Android-ウィジェットからRoomデータベースにアクセスする方法

ウィジェットクラス内のRoomDBにアクセスして、保存されているデータに従ってウィジェットを更新したかったのです。

ここでの問題は、ViewModelProviderが動作するためにフラグメントまたはアクティビティを必要とすることです。

ViewModelProviders.of(fragment).get(YourViewModel.class);

これはアプリウィジェットクラスでは利用できないので、どうすればよいですか?

7
Amr Ahmed

RemoteViewsService を使用してウィジェットUIにデータを入力する場合、AppWidgetProviderのonDataSetChanged()メソッドではなくonUpdate()メソッドにDAOクエリを含めることで、AsyncTaskの使用を回避できます。 。 onDataSetChanged()ドキュメント に記載されているように、

...高価なタスクは、このメソッド内で同期して安全に実行できます。暫定的に、古いデータがウィジェット内に表示されます。

ここでの他の利点は、アプリのViewModelオブザーバーのAppWidgetManager.notifyAppWidgetViewDataChanged()メソッドにonChanged()の呼び出しを含めることができることです。これによりonDataSetChanged()がトリガーされ、ウィジェットはonUpdate()の固定間隔ではなく、Roomデータベースが変更されるたびに更新されます。

2

viewModelを経由せずにRoomにアクセスできます。ViewModelはMVCやMVPと同様に、MVVMアーキテクチャのコンポーネントにすぎません。ViewModelがなくてもRoomにアクセスできます。コンテキストが必要です。

2
user10256891

久しぶりですが、この問題に出くわし、仲間のアーロン・デュニガン・アトリーのインスピレーションを受けて、何か役に立つものを追加したいと思いました。

基本的に、データベースと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()
            { ...

ささ

1
Javi

だからここで私の自己に答える。

機能した唯一の方法は、コンテキストを使用して抽象クラスから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);

}
1
Amr Ahmed

RoomからデータにアクセスするためにViewModelは必要ありません。どこからでもデータにアクセスできますが、データの変更が機能しないときに通知を受け取るというすばらしい機能があります。これを行うには、LiveData>ではなく単純なリストを返すメソッドをDaoオブジェクトに追加するだけです。そしてそれだけです。

0
Uzair

正確に、あなたはそれを行うことができます..あなたはすでにバックグラウンドスレッドからこのDAOクエリを作成する必要があるので、クエリを実行するためにコンテキストをAsyncTaskに渡すことは良い解決策ですが、代わりにAsyncTaskのコンストラクタでコンテキストを渡すようにしてくださいparamsでそれを渡します。

0
user10256891