【问题标题】:How to get data from one LiveData object to another within the ViewModel in android?如何在 android 的 ViewModel 中从一个 LiveData 对象获取数据到另一个对象?
【发布时间】:2019-04-04 20:40:30
【问题描述】:

我正在尝试创建一个通过房间和 LiveData 使用 SQL 数据库的应用程序。这是一个非常非常简单的测验应用程序。将显示一个问题和几个可能的答案。此外,还有一个下一个和上一个按钮来浏览问题。

有两个表格:“table_question”和“table_answer”。

table_question 由以下列组成:id、question

table_answer:id、answer、id_question

id_question 分配问题的答案,因为它是 1:n 关系。

我从数据库中以 LiveData 对象的形式获取所有问题和所有答案的列表。另一方面,我想要一个 LiveData 类 QuizWorld 来处理所有需要在屏幕上显示的数据(回答的问题、正确回答的问题、错误回答的问题、留下的问题等等)。 Activity 会观察到此类,以便更新 UI。

但是如何缩小两个 LiveData 列表“问题”和“答案”与创建 LiveData QuizWorld 之间的差距? QuizWorld 将需要保存在问题和答案中的那些信息,但 LiveData 对象没有构造函数。

我有使用 Transformations.switchMap 的想法,但无法实现。即使我忘记了 QuizWorld 类并在 ViewModel 中执行所有操作,也会给我留下无法访问 LiveData 列表的问题。

注意:实际上,列表不一定是 LiveData 对象,因为 SQL 数据库在运行时不会更改。我只是不知道如何通过房间访问数据库。但是,如果将来数据库变得更加动态(尚未计划),它仍然是一个不错的功能。

下面是部分代码:

public class MyViewModel extends AndroidViewModel{
     private Repository mRepository;

     private LiveData<List<Question>> questions;
     private LiveData<List<Answer>> answers;

     private LiveData<QuizWorld> mQuizWorld;

     public MyViewModel (Application application) {
          super(application);
          mRepository = new Repository(application);

          questions = mRepository.getQuestions;
          answers = mRepository.getAnswers;

          !!!!!Here should be the missing code I have no idea for!!!!!
     }

     public LiveData<QuizWorld> getQuizWorld(){
          return mQuizWorld;
     }

QuizWorld 类:

public class QuizWorld{
     private List<Question> questions;
     private List<Answer> answers;
     private int score;

     public QuizWorld(List<Question> questions, List<Answer> answers){
          this.questions = questions;
          this.answers = answers;

          init();          
     }

     private void init() {
          //do things with the questions and answers list
     }

     public int getScore(){
          return score;
     }
}

主活动:

    public class MainActivity {
         private LiveData<QuizWorld> mQuizWorld;
         private MyViewModel myViewModel;
         private TextView tvScore;

         @Override
         protected void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedinstanceState);
             setContenView(...);

             tvScore = (TextView) findViewById(R.id.tv_Score);
             myViewModel = ViewModelProvider.of(this).get(MyViewModel.class)

              mQuizViewModel.getQuizWorld().observe(this, new 
               Observer<QuizWorld>() {

                   @Override
                   public void onChanged(QuizWorld quizWorld){
                        tvScore.setText(quizWorld.getScore));
                        //show count of questions wrongly answered
                        //show count of questions remaining
                        //...
                   }
              }
         }
    }

【问题讨论】:

    标签: java android database android-architecture-components android-livedata


    【解决方案1】:

    我不完全确定你到底想要什么,但我宁愿建议你有一个包含一个问题及其答案的对象 QuestionWithAnswer,而不是两个不同的列表。然后,您可以在 dao 类中进行查询,该查询将返回该 QuestionWithAnswer 类(或在您的情况下为这些对象的列表)

    查看这个link 查询多个表(用户和宠物的示例应该看起来像你的) 在 Dao 类中,你会有类似的东西:

    @Query("SELECT id as isQuestion, question, id as idAnswer, answer " +
          "FROM table_question " +
          "LEFT JOIN table_answer on table_question.id = table_answer.id_question")
    public LiveData<List<QuestionWithAnswer>> loadResults();
    

    如果您想通过一个查询直接将对象包含在另一个对象中,请参阅此link

    或者,您可以进行转换,但我认为它不会非常有效,您会执行更多 SQL 查询,这通常对性能来说不是超级好(如果您有一个小型数据库,您不会注意到它) ,但对于其他具有更多数据的样本,您可以)。

    编辑:

    如果你需要在 QuizWorld 对象中转换 List,你可以像这样使用 Transformations.map 方法:

    quizWorldLiveData = Transformations.map(questionsWithAnswersLiveData, (data) -> new QuizWorld(data))
    

    【讨论】:

    • 好的,听起来不错,但不能解决我的问题。现在我的 ViewModel 中只有一个 LiveData>。我如何将此列表转移到我的 LiveData
    • 指定我的问题。我们只讨论 ViewModel 代码:我有一个来自 SQL (Room) 数据库的 LiveData> 对象。另一方面,我在 ViewModel 中创建了一个 LiveData。 QuizModel 需要 List 才能工作。 QuizWorld 如何从 LiveData> 中获取数据?转换有什么解决方案吗?
    • 我为此更新了答案。请注意,您可以在 map 方法中提供的函数中做任何您想做的事情。您可能需要添加弯括号来添加额外的行,例如: (data) -> { ...用一些代码行替换它... }
    猜你喜欢
    • 1970-01-01
    • 2021-11-09
    • 2011-09-08
    • 2019-08-24
    • 1970-01-01
    • 2020-08-11
    • 1970-01-01
    • 2020-09-17
    • 2023-04-11
    相关资源
    最近更新 更多