gpt4 book ai didi

android Room + livedata + observer onChaged工作逻辑及问题(特定 Action 下多次调用)

转载 作者:行者123 更新时间:2023-11-30 00:24:37 26 4
gpt4 key购买 nike

我有一个按照 MVVM 模式构建的 Android 应用程序。一切都运行良好,我真的很喜欢新的实时数据功能。但是,我一直在试图弄清楚为什么我会在我的应用程序中的特定类中看到这种奇怪的行为。我有这段代码:

public class MyFragment1 extends LifecycleFragment {
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
mViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
setHasOptionsMenu(true);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
getActivity().setTitle(R.string.mtitle);
View view = inflater.inflate(R.layout.afragment, container, false);

RecyclerView listView = (RecyclerView) view.findViewById(R.id.list);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
listView.setLayoutManager(mLayoutManager);
listView.setItemAnimator(new DefaultItemAnimator());
listView.setHasFixedSize(true);
adapter = new RoutesAdapter(new ArrayList<>());
listView.setAdapter(adapter);

Log.i(TAG, "Fragment OBSERVER count: " + getLifecycle().getObserverCount());
observer = (items) -> {
Log.i(TAG, "CHANGED OBSERVED");
adapter.setItems(items);

Log.i(TAG, "Fragment OBSERVER count: " + getLifecycle().getObserverCount());
Log.i(TAG,"getItems() HAS OBSERVERS:"+mViewModel.getItems().hasObservers());
};
mViewModel.getItems().observe(this,observer);

listView.addOnItemTouchListener(new MRecyclerTouchListener(getActivity().getApplicationContext(), listView, new MRecyclerTouchListener.ClickListener() {
@Override
public void onClick(View view, int position) {
item = adapter.getItemAtPosition(position);
MenuBottomSheetFragment mBottomSheetDialog = MenuBottomSheetFragment.newInstance();
mBottomSheetDialog.show(getFragmentManager(), "MenuBottomSheetFragment");
}
}));
return view;
}
}

如您所见,我有一个方法 getItems()返回 LiveData<List<>> (我正在使用 Room 库,所以 getItems 从数据库中获取并返回一个 LiveData 列表对象)。到目前为止,一切都很好!单击一个项目,我打开一个底部工作表对话框 fragment ,其中包含所选项目的选项。这是使用内部 static 创建的类如下所示:

public static class MenuBottomSheetFragment extends BottomSheetDialogFragment {

public MenuBottomSheetFragment(){}

public static MenuBottomSheetFragment newInstance(long routeId, Date timestart, Date timeend, long duration, double distance, String uid, long syncid) {
MenuBottomSheetFragment frag = new MenuBottomSheetFragment();
return frag;
}

@Override
public void setupDialog(final Dialog dialog, int style) {
super.setupDialog(dialog, style);
MyViewModel mViewModel = ViewModelProviders.of(getActivity()).get(MyViewModel.class);
View view = View.inflate(getContext(), R.layout.bottom_sheet, null);
dialog.setContentView(view);

TextView txtView = (TextView)view.findViewById( R.id.txt_view);

txtView.setOnClickListener((v)-> {
this.dismiss();
ViewFragment rvf = ViewFragment.newInstance();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.flContent, rvf, "ViewFragment");
ft.addToBackStack(null);
ft.commit();
});
}
}

我的 Activity 处理 6 个不同的 fragment (基于抽屉中的选择,用所选 fragment 替换当前 fragment )。从 Activity 中用上面的 fragment (MyFragment1) 替换一个 fragment ,观察者被注册一次并且工作得很好(即使在可见时再次从抽屉中选择它,因为它通过 onDestroy - 移除观察者 - 并重新创建它)。当用户单击 txtView 时出现问题。 .此操作将替换 MyFragment1ViewFragment .当用户点击后退按钮时,android 转到 MyFragment1再次但现在它创建了两个观察者,并且当用户在这 2 个 fragment 之间来回移动时它会继续创建(日志消息显示 # OBSERVER 计数,而不是只有 1,即使没有更改触发观察者)。

现在,我已经阅读了文档并浏览了 LiveData.java 的代码和 LifeCycleRegistry.java并注意到两件事:

  1. mViewModel.getItems().hasObservers()总是返回 false这意味着调用 observe()从不将其添加到观察者列表
  2. 但是,getLifecycle().getObserverCount()增加了 observe() 的倍数正在被调用(即从另一个 fragment 返回 fragment )

问题一为什么 LiveData hasObservers()返回 false,而所有者( fragment )的观察者计数似乎有观察者(LifeCycleRegistry.java)?据我了解,通过阅读代码,将观察者添加到所有者意味着首先应该将观察者添加到 Livedata使用方法的观察者列表 putIfAbsent如果对象已经存在,它会搜索该对象(它通过边缘条件和 if 检查,如果不存在则将其添加到本地观察者列表变量,然后添加到所有者观察者列表)。否则它会在添加任何内容之前返回。

问题2(相对于1)它在 docs 中说

if the given owner, observer tuple is already in the list, the call is ignored.

它现在似乎工作的方式是 observe()永远不会将调用添加到列表中(这里可能发生一件事:1)已经添加到观察列表中(不太可能至少是第一次)并且如果这是某种原因,那么它应该在将其添加到之前返回生命周期所有者观察者列表(因为它已经存在......对吗?),但不知何故,所有者列表的计数器每次都在增加。怎么了?

遍历 LiveData.java代码和observe() method 你会看到这个方法负责将可观察对象添加到 LiveData 的观察者列表中,还创建了这个对象的包装器并将其添加到所有者的生命周期观察者列表中。现在我相信它只发生在第二个(因为计数器)但还没有弄清楚为什么。

有人能帮忙吗?

提前致谢

最佳答案

问题 1 的答案:

看来,每次在 ViewModel 中更新 LiveData 时,您都会通过创建 LiveData 的新实例来观察错误的 LiveData。您必须返回相同的 LiveData 实例才能观察它并检查它是否有观察者。

例如在您的 ViewModel 中:

private LiveData<List<Items>> liveItems;

public void initItems(){
liveItems = wherever you get your Data;
}

public LiveData<List<Items>> getItems() {
return liveItems;
}

然后您可以通过以下方式在您的 Fragment 中观察 LiveData:

mViewModel.getItems().observe(this, observer)
...

然后,当您调用时:

mViewModel.getItems.hasObservers()     

它将返回 true。

关于android Room + livedata + observer onChaged工作逻辑及问题(特定 Action 下多次调用),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45616534/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com