LiveData 在使用 SyncAdapter / 不同线程更新时不会观察到变化
LiveData does not observe changes when updated with SyncAdapter / different Thread
我有一个插入消息的 SyncAdapter:
public class SyncAdapter extends AbstractThreadedSyncAdapter {
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
messageDAO.insert(..);
}
}
我有一个 Activity 显示这些消息的 已过滤 部分:
protected Observer<List<MessageEntity>> messageOberserver;
@Override
protected void onCreate(Bundle savedInstanceState) {
this.messageOberserver = new Observer<List<MessageEntity>>() {
@Override
public void onChanged(List<MessageEntity> messages) {
Log.v("tmp", "messages have changed");
messageAdapter.setData(messages);
}
}
MessageViewModel messageViewModel = ViewModelProviders.of(this).get(MessageViewModel.class);
messageDAO.findMessagesForTopic(this.topicId).observe(this, this.messageOberserver);
}
DAO:
@Query("SELECT * FROM Message WHERE messageTopicId = :topicId")
LiveData<List<MessageEntity>> messageDAO.findMessagesForTopic(String topicId);
现在的问题是观察者无法识别对消息的更改 table。如果我重新打开 activity,则会显示更改。 SyncAdapter 告诉 Activity 它应该检查更改的正确方法是什么?我读到了 postValue(),但我不知道如何使用它。 SyncAdapter 不知道 Activity.
显示的部分消息数据
--
顺便说一句。如果我从其他地方更新(不是 SyncAdapter),代码就可以工作。
您正在构建 messageOberserver
[原文如此] (messageObserver
)
this.messageOberserver = ...
在 将其传递到 observe
函数后。
observe(this, this.messageOberserver)
此时您的观察者为空。所以构造的观察者永远不会被注册,也永远不会被调用。
这可能是 运行 在另一个进程中设置您的同步适配器的结果,同步适配器服务文档默认指示该进程。尝试从 AndroidManifest.xml 中的服务中删除 android:process=":sync
或类似行。这将 运行 同步适配器与您的应用程序处于同一进程 activity。
如果您使用 Room 和多个进程,请确保启用 enableMultiInstanceInvalidation 以支持进程之间的更新通知。
fun getDatabase(context: Context): AppDatabase {
return synchronized(this) {
if (!Companion::INSTANCE.isInitialized) {
val instance = Room.databaseBuilder(
context,
AppDatabase::class.java,
"media"
)
// TODO support migrations
.fallbackToDestructiveMigration()
.enableMultiInstanceInvalidation()
.build()
INSTANCE = instance
}
INSTANCE
}
}
我有一个插入消息的 SyncAdapter:
public class SyncAdapter extends AbstractThreadedSyncAdapter {
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
messageDAO.insert(..);
}
}
我有一个 Activity 显示这些消息的 已过滤 部分:
protected Observer<List<MessageEntity>> messageOberserver;
@Override
protected void onCreate(Bundle savedInstanceState) {
this.messageOberserver = new Observer<List<MessageEntity>>() {
@Override
public void onChanged(List<MessageEntity> messages) {
Log.v("tmp", "messages have changed");
messageAdapter.setData(messages);
}
}
MessageViewModel messageViewModel = ViewModelProviders.of(this).get(MessageViewModel.class);
messageDAO.findMessagesForTopic(this.topicId).observe(this, this.messageOberserver);
}
DAO:
@Query("SELECT * FROM Message WHERE messageTopicId = :topicId")
LiveData<List<MessageEntity>> messageDAO.findMessagesForTopic(String topicId);
现在的问题是观察者无法识别对消息的更改 table。如果我重新打开 activity,则会显示更改。 SyncAdapter 告诉 Activity 它应该检查更改的正确方法是什么?我读到了 postValue(),但我不知道如何使用它。 SyncAdapter 不知道 Activity.
显示的部分消息数据--
顺便说一句。如果我从其他地方更新(不是 SyncAdapter),代码就可以工作。
您正在构建 messageOberserver
[原文如此] (messageObserver
)
this.messageOberserver = ...
在 将其传递到 observe
函数后。
observe(this, this.messageOberserver)
此时您的观察者为空。所以构造的观察者永远不会被注册,也永远不会被调用。
这可能是 运行 在另一个进程中设置您的同步适配器的结果,同步适配器服务文档默认指示该进程。尝试从 AndroidManifest.xml 中的服务中删除 android:process=":sync
或类似行。这将 运行 同步适配器与您的应用程序处于同一进程 activity。
如果您使用 Room 和多个进程,请确保启用 enableMultiInstanceInvalidation 以支持进程之间的更新通知。
fun getDatabase(context: Context): AppDatabase {
return synchronized(this) {
if (!Companion::INSTANCE.isInitialized) {
val instance = Room.databaseBuilder(
context,
AppDatabase::class.java,
"media"
)
// TODO support migrations
.fallbackToDestructiveMigration()
.enableMultiInstanceInvalidation()
.build()
INSTANCE = instance
}
INSTANCE
}
}