Android - 如何从小部件访问 Room 数据库
Android - How to access Room database from widget
我想访问我的小部件中的 Room DB class 以根据存储的数据更新小部件。
这里的问题是 ViewModelProvider 需要片段或 activity 才能使用..
ViewModelProviders.of(fragment).get(YourViewModel.class);
在应用程序小部件中不可用 class 那么该怎么做?
不通过ViewModel也可以访问Room。ViewModel只是MVVM架构的一个组成部分,就像MVC或MVP一样。没有ViewModel,你仍然可以访问Room,你只需要有一个上下文
所以在这里回答我自己..
唯一可行的方法是使用上下文从抽象中获取数据库实例 class 和 运行 DAO 直接在后台线程中查询而无需 ViewModelProviders class
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);
}
确实如此,您可以这样做..您已经需要从后台线程进行此 DAO 查询,因此将上下文传递给 AsyncTask 以执行查询是一个很好的解决方案,但请尝试在构造函数中传递上下文的 AsyncTask 而不是在参数中传递它。
您可以编写一个存储库 class,并使用它来异步访问您的 Room 数据库。
示例:https://codelabs.developers.google.com/codelabs/android-room-with-a-view/#7
如果您使用 RemoteViewsService to populate your widget UI, then you can avoid using an AsyncTask by including a DAO query in its onDataSetChanged()
method, rather than in the AppWidgetProvider's onUpdate()
method. As stated in the onDataSetChanged()
documentation,
...expensive tasks can be safely performed synchronously within this method. In the interim, the old data will be displayed within the widget.
此处的另一个优点是您可以在应用的 ViewModel 观察器的 onChanged()
方法中包含对 AppWidgetManager.notifyAppWidgetViewDataChanged()
的调用;这将触发 onDataSetChanged()
并且每次 Room 数据库更改时小部件都会更新,而不是仅在 onUpdate()
.
的固定时间间隔内更新
您不需要 ViewModel 来访问 Room 中的数据。您可以从任何地方访问数据,唯一需要注意的是,当数据更改时收到通知的出色功能不起作用。为此,只需向您的 Dao 对象添加一个方法,该方法 return 是一个简单的列表而不是 LiveData>。就是这样。
我知道已经有一段时间了,但我刚刚遇到这个问题,想根据同事 Aaron-dunigan-atlee 的启发添加一些有用的东西。
基本上显示了数据库和 Dao 对象的去向...更重要的是,onDataSetChanged()
调用 Room 查询的方法。
该示例用于记笔记应用程序来说明,正如上面评论的那样,任何地方都不需要 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()
{ ...
莎莎
在 JaviMar 在 Kotlin 中的回答中添加了一些关于如何将某些东西组合在一起的更多信息:
class RoomWidgetService : RemoteViewsService() {
override fun onGetViewFactory(intent: Intent): RemoteViewsFactory {
return RoomRemoteViewsFactory(this.applicationContext, intent)
}
}
class RoomRemoteViewsFactory(private val context: Context, intent: Intent) : RemoteViewsService.RemoteViewsFactory {
private var todos: List<TodoItem> = listOf()
private lateinit var todoDao: TodoDao
override fun onCreate() {
val database = TodoRoomDatabase.getDatabase(context)
todoDao = database.todoDao()
}
override fun onDataSetChanged() {
todos = todoDao.getTodosSync()
}
// rest of class...
}
我通过观察某些东西来通知小部件更新。您可以在主 activity 或应用程序中观察 ViewModel。不确定观察数据的最佳位置。
todoViewModel.todoItems.observe(this) {
val appWidgetManager = AppWidgetManager.getInstance(applicationContext)
val thisAppWidget = ComponentName(
applicationContext.packageName,
RoomWidget::class.java.name
)
val appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget)
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.list_view )
}
我想访问我的小部件中的 Room DB class 以根据存储的数据更新小部件。
这里的问题是 ViewModelProvider 需要片段或 activity 才能使用..
ViewModelProviders.of(fragment).get(YourViewModel.class);
在应用程序小部件中不可用 class 那么该怎么做?
不通过ViewModel也可以访问Room。ViewModel只是MVVM架构的一个组成部分,就像MVC或MVP一样。没有ViewModel,你仍然可以访问Room,你只需要有一个上下文
所以在这里回答我自己..
唯一可行的方法是使用上下文从抽象中获取数据库实例 class 和 运行 DAO 直接在后台线程中查询而无需 ViewModelProviders class
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); }
确实如此,您可以这样做..您已经需要从后台线程进行此 DAO 查询,因此将上下文传递给 AsyncTask 以执行查询是一个很好的解决方案,但请尝试在构造函数中传递上下文的 AsyncTask 而不是在参数中传递它。
您可以编写一个存储库 class,并使用它来异步访问您的 Room 数据库。
示例:https://codelabs.developers.google.com/codelabs/android-room-with-a-view/#7
如果您使用 RemoteViewsService to populate your widget UI, then you can avoid using an AsyncTask by including a DAO query in its onDataSetChanged()
method, rather than in the AppWidgetProvider's onUpdate()
method. As stated in the onDataSetChanged()
documentation,
...expensive tasks can be safely performed synchronously within this method. In the interim, the old data will be displayed within the widget.
此处的另一个优点是您可以在应用的 ViewModel 观察器的 onChanged()
方法中包含对 AppWidgetManager.notifyAppWidgetViewDataChanged()
的调用;这将触发 onDataSetChanged()
并且每次 Room 数据库更改时小部件都会更新,而不是仅在 onUpdate()
.
您不需要 ViewModel 来访问 Room 中的数据。您可以从任何地方访问数据,唯一需要注意的是,当数据更改时收到通知的出色功能不起作用。为此,只需向您的 Dao 对象添加一个方法,该方法 return 是一个简单的列表而不是 LiveData>。就是这样。
我知道已经有一段时间了,但我刚刚遇到这个问题,想根据同事 Aaron-dunigan-atlee 的启发添加一些有用的东西。
基本上显示了数据库和 Dao 对象的去向...更重要的是,onDataSetChanged()
调用 Room 查询的方法。
该示例用于记笔记应用程序来说明,正如上面评论的那样,任何地方都不需要 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()
{ ...
莎莎
在 JaviMar 在 Kotlin 中的回答中添加了一些关于如何将某些东西组合在一起的更多信息:
class RoomWidgetService : RemoteViewsService() {
override fun onGetViewFactory(intent: Intent): RemoteViewsFactory {
return RoomRemoteViewsFactory(this.applicationContext, intent)
}
}
class RoomRemoteViewsFactory(private val context: Context, intent: Intent) : RemoteViewsService.RemoteViewsFactory {
private var todos: List<TodoItem> = listOf()
private lateinit var todoDao: TodoDao
override fun onCreate() {
val database = TodoRoomDatabase.getDatabase(context)
todoDao = database.todoDao()
}
override fun onDataSetChanged() {
todos = todoDao.getTodosSync()
}
// rest of class...
}
我通过观察某些东西来通知小部件更新。您可以在主 activity 或应用程序中观察 ViewModel。不确定观察数据的最佳位置。
todoViewModel.todoItems.observe(this) {
val appWidgetManager = AppWidgetManager.getInstance(applicationContext)
val thisAppWidget = ComponentName(
applicationContext.packageName,
RoomWidget::class.java.name
)
val appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget)
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.list_view )
}