android - 发布或设置 MutableLiveData - 未调用观察者 onChanged

标签 android android-fragments rx-android android-livedata android-viewmodel

我发现了新的 Android 架构组件,我想通过一个小型测试应用程序来测试 ViewModel/LiveData 。后者有两个 fragment (在 ViewPager 中),第一个创建/更新卡片列表(通过 EditText),第二个显示所有卡片。

我的 View 模型:


public class CardsScanListViewModel extends AndroidViewModel {

    private MutableLiveData> cardsLiveData = new MutableLiveData();
    private HashMap cardsMap = new HashMap();

    public CardsScanListViewModel(@NonNull Application application) {
        super(application);
    }

    public MutableLiveData> getCardsLiveData() {
        return this.cardsLiveData;
    }

    public void saveOrUpdateCard(String id) {
        if(!cardsMap.containsKey(id)) {
            cardsMap.put(id, new Card(id, new AtomicInteger(0)));
        }
        cardsMap.get(id).getCount().incrementAndGet();
        this.cardsLiveData.postValue(cardsMap);
    }
}

我的第二个 fragment :

public class CardsListFragment extends Fragment {

    CardsAdapter cardsAdapter;

    RecyclerView recyclerCardsList;

    public CardsListFragment() {}

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final CardsScanListViewModel viewModel =
                ViewModelProviders.of(this).get(CardsScanListViewModel.class);

        observeViewModel(viewModel);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_cards_list, container, false);
        recyclerCardsList = v.findViewById(R.id.recyclerCardsList);
        recyclerCardsList.setLayoutManager(new LinearLayoutManager(getActivity()));
        cardsAdapter = new CardsAdapter(getActivity());
        recyclerCardsList.setAdapter(cardsAdapter);

        return v;
    }

    private void observeViewModel(CardsScanListViewModel viewModel) {
        viewModel.getCardsLiveData().observe(this, new Observer  > () {
            @Override
            public void onChanged(@Nullable HashMap  cards) {
                if (cards != null) {
                    cardsAdapter.setCardsList(cards.values());
                }
            }
        });
    }
}

HashMap 与我的 MutableLiveData 一样,更新得很好,但我的第二个 fragment 没有通过观察者接收信息。

最佳答案

您正在观察ViewModel新实例而不是观察相同的ViewModel由您的第一个 fragment 使用。

final CardsScanListViewModel viewModel =
            ViewModelProviders.of(this).get(CardsScanListViewModel.class);

以上代码初始化 CardsScanListViewModel 的新实例对于你的第二个 fragment CardsListFragment ,因为你通过了this作为上下文。 如果您更新此 fragment 中的任何数据,它将在 ViewModel 的这个实例更新。 .

它适用于您的第一个 fragment ,因为它更新数据并观察来自 ViewModel 的同一实例的数据。

为了保持 ViewModel 之间的数据通用,通过在两个 fragment 中传递 Activity 上下文而不是 fragment 上下文来启动 View 模型。

final CardsScanListViewModel viewModel =
            ViewModelProviders.of(getActivity()).get(CardsScanListViewModel.class);

这将创建 CardsScanListViewModel单个实例并且数据将在 fragment 之间共享,因为它们正在观察 LiveData来自ViewModel单个实例 .

为了进行确认,如果您尚未在适配器本身中执行此操作,则需要在更新列表后添加 notificationDataSetChanged()

private void observeViewModel(CardsScanListViewModel viewModel) {
    viewModel.getCardsLiveData().observe(this, new Observer  > () {
        @Override
        public void onChanged(@Nullable HashMap  cards) {
            if (cards != null) {
                cardsAdapter.setCardsList(cards.values());
                cardsAdapter.notifyDataSetChanged();
            }
        }
    });
}

关于android - 发布或设置 MutableLiveData - 未调用观察者 onChanged,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48033119/

相关文章:

android - RxJava mixLatest - 可从更改中观察到

java - 从编辑文本创建一个 Observable

android - 在 Google AppEngine 上运行部署的应用程序时出现问题

javascript - HTML/JS - 检测 Android 软件版本(和切换 css 文件)

java - 如何通过另一个fragment中的onClick调用一个fragment中的方法?

android - 每个 fragment 的自定义选项菜单

android - 使用 Intent 时如何销毁和创建新的 Activity 实例

android - 如何仅在 EditText 中获取最后一次输入? (安卓)

Android:抽屉导航标题 TextView 未以编程方式设置

android - RxAndroid & Retrofit 处理错误的最佳方法