当我在 ViewModel 中收到 DAO 查询的第一个结果后需要删除观察者时,@CommonsWare 和 @Toni Joe 提出的解决方案并没有为我解决问题。但是,在 Livedata 上找到的以下解决方案在调用 removeObserer 后保持观察者为我做了一些我自己的直觉。
过程如下,根据请求在 ViewModel 中创建一个存储 LiveData 的变量,在执行 null 检查后在活动中的创建观察者函数调用中检索它,并在调用 flushToDB 例程之前调用删除观察者函数导入类。也就是说,我的 ViewModel 中的代码如下所示:
public class GameDataModel extends AndroidViewModel {
private LiveData<Integer> lastMatchNum = null;
.
.
.
private void initLastMatchNum(Integer player1ID, Integer player2ID) {
List<Integer> playerIDs = new ArrayList<>();
playerIDs.add(player1ID);
playerIDs.add(player2ID);
lastMatchNum = mRepository.getLastMatchNum(playerIDs);
}
public LiveData<Integer> getLastMatchNum(Integer player1ID, Integer player2ID) {
if (lastMatchNum == null) { initLastMatchNum(player1ID, player2ID); }
return lastMatchNum;
}
在上面,如果 ViewModel 中的 LiveData 变量中没有数据,我会调用initLastMatchNum()
以从视图模型中的函数中检索数据。要从活动中调用的函数是getLastMatchNum()
。该例程检索 ViewModel 中变量中的数据(通过 DAO 通过存储库检索)。
我的活动中有以下代码
public class SomeActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
.
.
.
setupLastMatchNumObserver();
.
.
.
}
private void setupLastMatchNumObserver() {
if (mGameDataViewModel.getLastMatchNum(Player1ID, Player2ID).hasObservers()) {
Log.v("Observers", "setupLastMatchNumObserver has observers...returning");
return;
}
Log.v("Setting up Observers", "running mGameDataViewModel.get...observer()");
mGameDataViewModel.getLastMatchNum(Player1ID, Player2ID).observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer MatchNumber) {
if (MatchNumber == null ) {
matchNumber = 1;
Log.v( "null MatchNumber", "matchNumber: " + matchNumber.toString());
}
else {
matchNumber = MatchNumber; matchNumber++;
Log.v( "matchNumber", "Incrementing match number: " + matchNumber.toString());
}
MatchNumberText.setText(matchNumber.toString());
}
});
}
private void removeObservers() {
final LiveData<Integer> observable = mGameDataViewModel.getLastMatchNum(Player1ID, Player2ID);
if (observable != null && observable.hasObservers()) {
Log.v("removeObserver", "Removing Observers");
observable.removeObservers(this);
}
}
上面发生的事情是 1.) 我setupLastMatchNumObserver()
在活动的方法中调用例程onCreate
,以更新类的变量matchNum
。这会跟踪存储在数据库中的游戏中玩家之间的匹配数。每组球员在数据库中都会有不同的比赛编号,这取决于他们彼此进行新比赛的频率。这个线程中的第一个解决方案对我来说似乎有点厌倦,因为在其中调用 remove 观察者onChanged
对我来说似乎很奇怪,并且会TextView
在玩家每次移动的每次数据库刷新后不断更改对象。每次移动后都会增加,matchNumber
因为在第一次移动后数据库中有一个新值(即一个matchNumber++
值)并onChanged
一直被调用,因为removeObservers
没有按预期工作。setupLastMatchNumObserver()
检查是否有实时数据的观察者,如果有,则不会在每一轮实例化一个新调用。如您所见,我正在设置一个TextView
对象来反映玩家的当前比赛编号。
下一部分是关于何时调用的小技巧removeObservers()
。起初我想如果我setupLastMatchNumObserver()
在onCreate
覆盖活动之后直接调用它,一切都会好起来的。但它在观察者获取数据之前移除了观察者。我发现如果我removeObservers()
在调用之前直接调用以将活动中收集的新数据刷新到数据库中(在整个活动中的单独例程中),它就像一个魅力。IE,
public void addListenerOnButton() {
.
.
.
@Override
public void onClick(View v) {
.
.
.
removeObservers();
updateMatchData(data);
}
}
我也以上述方式在我的活动中removeObservers();
和其他地方打电话。updateMatchData(data)
可以根据需要多次调用美女removeObservers()
,因为如果没有观察者在场,则会返回检查。