【问题标题】:Post or Set MutableLiveData - Observer onChanged not called发布或设置 MutableLiveData - 未调用观察者 onChanged
【发布时间】:2017-12-30 10:38:13
【问题描述】:

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

我的 ViewModel:


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);
    }
}

我的第二个片段:

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 一样,更新良好,但我的第二个片段没有通过观察者接收信息。

【问题讨论】:

  • 有关信息,一个简单的 MutableLiveData (set & get) 在我的 ViewPager 的第一个片段中工作。我试图扭转这两个片段,但仍然是同样的问题。我将 HashMap 更改为 List 但仍然没有更新。我也用 HasObserver 做了测试,结果是错误的(没有观察者)。
  • 我几天前使用单个 ViewModel 实例添加了解决方案。让我知道它是否适合你

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


【解决方案1】:

您正在观察ViewModel新实例,而不是观察您的第一个片段使用的ViewModel。 p>

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

以上代码为您的第二个片段CardsListFragment 初始化CardsScanListViewModel 的新实例,因为您将this 作为上下文传递。 如果您更新此片段中的任何数据,它将在ViewModel 的此实例更新

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

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

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

这将创建CardsScanListViewModel单个实例,并且当片段从ViewModel单个实例 观察LiveData 时,数据将在片段之间共享。 p>

为了确认,如果您没有在适配器本身中这样做,则需要在更新列表后添加 notifyDataSetChanged()

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();
            }
        }
    });
}

【讨论】:

  • 嗨@adityakamble49,谢谢你的回答。是的,所有 ViewModelProviders.of(getActivity()) 之间的 Context 必须相同,以便与 ViewModel 进行良好的通信。我有第一个片段,他用“this”更新后者作为上下文。我将其更改为 getActivity()。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-09
  • 2019-09-18
  • 2019-06-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多