【问题标题】:How can I make one ViewModel class return multiple data types to an activity or a fragment如何让一个 ViewModel 类将多种数据类型返回到活动或片段
【发布时间】:2018-06-23 09:21:40
【问题描述】:

我正在阅读这篇博客文章Using Android Architecture Components with Firebase Realtime Database (Part 2) ,并且我正在实现最后一个代码 sn-p 及其工作。

private final FirebaseQueryLiveData liveData = new FirebaseQueryLiveData(HOT_STOCK_REF);
private final MediatorLiveData<HotStock> hotStockLiveData = new MediatorLiveData<>();

public HotStockViewModel() {
    // Set up the MediatorLiveData to convert DataSnapshot objects into HotStock objects
    hotStockLiveData.addSource(liveData, new Observer<DataSnapshot>() {
        @Override
        public void onChanged(@Nullable final DataSnapshot dataSnapshot) {
            if (dataSnapshot != null) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        hotStockLiveData.postValue(dataSnapshot.getValue(HotStock.class));
                    }
                }).start();
            } else {
                hotStockLiveData.setValue(null);
            }
        }
    });
}

我实际上是在使用它来返回一个包含在 LiveData 中的 HotStockViewModel 对象数组(通过循环访问数据库中的结果,我真的不知道我是否应该在 ViewModel 类中执行此数据操作)并返回将数组转换为仅显示它的片段。

是否可以使用同一个 ViewModel 类来返回仅包含 LiveData 中的价格的数组(并且仍然返回包含在 LiveData 中的 HotStockViewModel 对象的数组)?

如果是,我该如何实现?我不想返回一个包含在 LiveData 中的 HotStockViewModel 对象数组,然后循环遍历它以获取片段中的价格。我根本不希望片段做任何数据操作,只显示数据。

我看到了这个 stackoverflow 问题Can an Android Architecture Components ViewModel compose an object from multiple LiveData returning models?,但我不明白答案。我还是 Java 初学者。

【问题讨论】:

    标签: android firebase firebase-realtime-database android-architecture-components android-viewmodel


    【解决方案1】:

    我真的不知道我是否应该在 一个 ViewModel 类

    在我认为您正在使用的 Android MVVM 模式中,不建议在 Viewmodel 类中执行数据操作。而是创建一个应该处理这个的 repo 类。 viewModel 类应该只从 repo 类中获取数据,然后将其传递给需要它的任何 UI 组件。

    【讨论】:

    • 那么如果是这种情况(我真的不知道如何创建一个 repo。我昨天正在寻找它但我找不到一个可以理解的实现)我可以创建一个 repo 并通过从数据库到这个 repo 的直接 dataSnapshot 并让这个 repo 做我所有的数据操作(包括只提取价格并将它们放在一个数组列表中),然后将此数据传递给视图。如果这是可行的,请问我该如何实现?
    【解决方案2】:

    是否可以使用同一个 ViewModel 类返回一个数组 只有包裹在 LiveData 中的价格(并且仍然返回一个数组 包裹在 LiveData 中的 HotStockViewModel 对象)

    您可以创建一个数据类,例如

     public class ResponseData {
                private ArrayList<HotStock> hotstockVm;
                private ArrayList<double> prices;
    
                public ArrayList<double> getPrices(){
                  return prices;
                };
    
                public void setPrices(ArrayList<double>prices ){
                  this.prices = prices;
                };
        }
    

    然后你创建一个 repo 类

        public class Repo{
    
        private final FirebaseQueryLiveData liveData = new FirebaseQueryLiveData(HOT_STOCK_REF);
        private final MediatorLiveData hotStockLiveData = new MediatorLiveData();
        private ResponseData response = new ResponseData();
        private ArrayList<HotStock> hotstock = new ArrayList<>();
        private ArrayList<Double> prices = new ArrayList<>();
    
    
        public LiveData<ResponseData> getData() {
            //a mutableLivedata to hold data got
            final MutableLivedata<ResponseData> dataMutableLiveData = new MutableLivedata<>();
            // Set up the MediatorLiveData to convert DataSnapshot objects into HotStock objects
            hotStockLiveData.addSource(liveData, new Observer() {
                @Override
                public void onChanged(@Nullable final DataSnapshot dataSnapshot) {
                    if (dataSnapshot != null) {
                        new Thread(new Runnable() {
                            @Override
                            public void run() {
                                hotStockLiveData.postValue(dataSnapshot.getValue(HotStock.class));
                                //get each hotstock object from firebase
                                HotStock object = dataSnapshot.getValue(HotStock.class);
                                //get the price from each hotstock object
                                //if class HotStock has arrays of inner class where price is, then loop to get price.
                                //assign price to a new list
                                //assign also hotstock to a new list.
                                prices.add(object.getPrice);
                                hotstock.add(object);
    
                                //set the value of all
                                response.setHotstock(hotstock);
                                response.setPrices(prices);
    
                                dataMutableLiveData.postValue(response);
    
                            }
                        }).start();
                    } else {
                        hotStockLiveData.setValue(null);
                    }
                }
            });
            return dataMutableLiveData;
        }
    }
    

    然后你可以创建一个viewModel类

    public class AppViewModel extends ViewModel{
    
        private LiveData<ResponseData> dataLiveData;
        private Repo appRepo;
    
        public AppViewModel(){
            appRepo = new Repo();
        }
    
        public LiveData<ResponseData> getLiveData(){
            if(dataLiveData == null){
                  dataLiveData = appRepo.getData();
                  return dataLiveData;
            }
    
        }
    }
    

    用法

    public class MainActivity extends Activity{
    
        AppViewModel appViewModel;
    
        public void onCreate(Bundle SavedInstanceState){
            super.onCreate(SavedInstanceState);
            appViewModel = ViewModelProviders.of(this).get(AppViewModel.class);
    
            appViewModel.getLiveData().observe(this,response -> {
                //here response is an object of type ResponseData.
                //in this response object you can get your arraylist of prices and also arraylist of hotstock
    
    
            });
        }
    }
    

    【讨论】:

    • 我试过这个。正在调用 getData() 方法,但未调用 onChanged() 方法。我没有得到任何价值,在跟踪之后我发现我的 FirebaseQueryLiveData 类中的方法也没有被调用
    • 非常感谢。我现在已经能够修复它了。 hotStockLiveData 对象应该将其值发布为 hotStockLiveData.postValue(response);而且我根本没有使用 dataMutableLiveData,我返回的是 hotStockLiveData 而不是 dataMutableLiveData。请更新您的答案,以便我将其标记为正确。非常感谢!
    • 嗨,@sudo_kaizen 上面的答案是 George 更新的吗?如果没有,你能更新吗?因为我和你有同样的问题,但不明白什么是确切的答案!谢谢。
    • 嗨@RuchaBhattJoshi,在检查我们谈话之间的日期时,我看到我的评论是 6 月 26 日,他的评论是 6 月 23 日,所以他没有更新答案。你可以结合他的回答和我的评论来解决你的问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-23
    • 2019-10-10
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    相关资源
    最近更新 更多