当前位置: 首页 > 知识库问答 >
问题:

Android架构组件ViewModel可以从多个LiveData返回模型组成一个对象吗?

麹高远
2023-03-14

这可能吗?我是否需要为我的模型放弃LiveData而求助于不同的观察模式/工具?

编辑:已添加伪代码。我的实际类要复杂和冗长得多。我希望我的意图是可以理解的。

// OneDataModel.kt
class oneDataModel {
    val oneDataElement = ""
}

// AnotherDataModel.kt
class anotherDataModel {
    val anotherDataElement = 19
}

// OneDataRepository.kt
class OneDataRepository {
    val oneDataSet = MutableLiveData<MutableList<oneDataModel>>()

    private val dataListener = object: ChildEventListener {
        override fun onChildAdded(snapshot: DataSnapshot, p1: String?) {
            val newChild = snapshot.getValue(oneDataModel::class.java)
            if (newChild != null) {
                oneDataSet.value?.add(newChild)
            }
        }
    }

    init {
        oneDataSet.value = mutableListOf<oneDataModel>()
        OneNetworkDataTable.addListener(dataListener)
    }
}

// AnotherDataRepository.kt
class AnotherDataRepository {
    var anotherDataSet = MutableLiveData<MutableList<anotherDataModel>>()

    private val dataListener = object: ChildEventListener {
        override fun onChildAdded(snapshot: DataSnapshot, p1: String?) {
            val newChild = snapshot.getValue(anotherDataModel::class.java)
            if (newChild != null) {
                anotherDataSet.value?.add(newChild)
            }
        }
    }

    init {
        anotherDataSet.value = mutableListOf<anotherDataModel>()
        AnotherNetworkDataTable.addListener(dataListener)
    }
}

// ComposedViewModel.kt
class ComposedViewModel: ViewModel() {
    class ComposedItem {
        var dataName: String = ""   // From OneDataRepository items
        var dataValue: Int = -1     // From AnotherDataRepository items
    }
    var publishedDataSet = MutableLiveData<MutableList<ComposedItem>>()

    //***
    //*** WHAT GOES HERE? HOW DO I LISTEN TO EACH OF THE DATA REPOSITORIES AND BUILD UP COMPOSED
    //*** ITEMS FOR THE UI?
    //***
}

// MyFragment.kt
class MyFragment : Fragment() {
    private val composedViewModel: ComposedViewModel by lazy { ViewModelProviders.of(activity).get(ComposedViewModel::class.java) }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.fragment_feed, container, false)

        recyclerView.adapter = UIAdapter

        composedViewModel.publishedDataSet.observe(this, Observer {
            UIAdapter.notifyDataSetChanged()
        })

        return view
    }
}

共有1个答案

邹桐
2023-03-14

希望我的作品能满足你的问题。

我以前做过一个样例项目,现在把另一个假的livedata集成到这个视图模型中。文件差异

使用MediatorLiveData类将多个数据源包装为一个。

public class FeedEntryListViewModel extends ViewModel {

  //list all your live data here
  private LiveData<List<FeedEntry>> feedEntries = new MutableLiveData<>();
  private MutableLiveData<String> userId = new MutableLiveData<>();
  //show your composite model here
  private MediatorLiveData<CompositeModel> compositeModelLiveData;

  //list all your repository
  private FeedEntryRepository feedEntryDBRepository;

  /*
  The complete model to show the data
   */
  public static class CompositeModel {

    String userId = "SystemId";
    private List<FeedEntry> feedEntries = new ArrayList<>();


    public String getUserId() {
      return userId;
    }

    public void setUserId(String userId) {
      this.userId = userId;
    }

    public List<FeedEntry> getFeedEntries() {
      return feedEntries;
    }

    public void setFeedEntries(
        List<FeedEntry> feedEntries) {
      this.feedEntries = feedEntries;
    }


  }

  public FeedEntryListViewModel(
      FeedEntryRepository feedEntryDBRepository) {
    this.feedEntryDBRepository = feedEntryDBRepository;
    this.feedEntries = feedEntryDBRepository.getAll();
    this.compositeModelLiveData = new MediatorLiveData<>();
    this.compositeModelLiveData.addSource(feedEntries, data ->
    {
      CompositeModel compositeModel = compositeModelLiveData.getValue();
      compositeModel.setFeedEntries(data);
      compositeModelLiveData.postValue(compositeModel);
    });
    this.compositeModelLiveData.addSource(userId, data -> {
      CompositeModel compositeModel = compositeModelLiveData.getValue();
      compositeModel.setUserId(data);
      compositeModelLiveData.postValue(compositeModel);
    });
    //initialize the composite model to avoid NullPointerException
    this.compositeModelLiveData.postValue(new CompositeModel());
  }

  public void loadUserId(String userId) {
    this.userId.setValue(userId);
  }

  public LiveData<List<FeedEntry>> getFeedEntrys() {
    return feedEntryDBRepository.getAll();
  }

  public LiveData<CompositeModel> getCompositeEntrys() {
    return compositeModelLiveData;
  }

  public LiveData<List<FeedEntry>> insert(FeedEntry... feedEntries) {
    feedEntryDBRepository.insertAll(feedEntries);
    return feedEntryDBRepository.getAll();
  }

  public void delete(FeedEntry feedEntry) {
    feedEntryDBRepository.delete(feedEntry);
  }


  public int update(FeedEntry feedEntry) {
    return feedEntryDBRepository.update(feedEntry);
  }

}
viewModel.getCompositeEntrys().observe(this, entries -> {...});
 public FeedEntryListViewModel(
      FeedEntryRepository feedEntryDBRepository) {
    this.feedEntryDBRepository = feedEntryDBRepository;
    this.feedEntries = feedEntryDBRepository.getAll();
    this.compositeModelLiveData = new MediatorLiveData<>();
    this.compositeModelLiveData.addSource(feedEntries, data ->
    {
      CompositeModel compositeModel = compositeModelLiveData.getValue();
      compositeModel.setFeedEntries(data);
      compositeModelLiveData.postValue(compositeModel);
    });
    this.compositeModelLiveData.addSource(userId, data -> {
      CompositeModel compositeModel = compositeModelLiveData.getValue();
      compositeModel.setUserId(data);
      compositeModelLiveData.postValue(compositeModel);
    });
    //initialize the composite model to avoid NullPointerException
    this.compositeModelLiveData.postValue(new CompositeModel());
  }
 类似资料:
  • 我有一组这样的对象: 我想对其进行过滤,以便每个唯一名称都有一个实例,该实例必须给出小于或等于40的最大值。如果过滤,上述情况将返回: 最终的数组不必按任何特定的顺序排序。

  • 我正在研究Android架构组件,我有点困惑。在这个示例中,它们使用一个存储库,并通过ViewModels观察存储库数据源中的更改。我不明白datasource中的更改是如何推送到ViewModels的,因为在ViewModels中看不到将它们订阅到存储库的任何代码。类似地,片段观察ViewModel的LiveData,但它们实际上订阅了LiveData: 我在ViewModels中看不到任何类型

  • 嗨,我有一个对象,它正在使用一个组件中的可观察到的东西从api更新,我想捕获同一对象对另一个组件的更改。这两个组件都是两个选项卡。最初是根据路由更新数据。以下是正在更新的数据: 我在这里捕获数据: 在中,数据最初是从路由获取的。考虑到上述情况,我有两个问题: 如果应用程序有多个组件,我想我必须在每个组件中事件,这将是一个很好的做法。请提出任何替代方法? 由于数据来自服务器,为什么不从中的获取更新的

  • 问题内容: 例如,对于读取数组元素的单个方法,程序员如何允许对象数组或基元数组作为参数传递?将仅接受对象数组,而泛型变量则不接受基元。有没有办法在不重载方法的情况下接受任一类型的数组? 问题答案: 您可以将任一类型的数组作为传递。 从那里开始,您必须使用反射。特别是,和会告诉方法已传递的内容。这是原始数据类型引入的一些不幸的不统一。