【问题标题】:Room without LiveData没有 LiveData 的房间
【发布时间】:2019-07-09 01:45:54
【问题描述】:

我正在试验Room 数据库。 我不希望我的数据被观察,我只想从数据库中获取数据一次。如何使用 MVVM 实现这一点?

我面临的问题:如果我尝试在没有AsyncTask 的情况下获取数据,它会给出: 无法访问主线程上的数据库,因为它可能会长时间锁定 UI(如预期的那样),如果我使用 AsyncTask,该方法返回 null List,因为方法在 AsyncTask 完成之前返回。

道类:

@Query("SELECT * FROM student_table where StudentName = :studentName")List<Student> getStudentWithSameName(String studentName);

存储库:

public List<Student> getAllStudentWithSameName(String studentName) {
    new GetAllStudentWithSameNameAsyncTask(studentDao).execute(studentName);
    return studentsWithSameName;
}



private class GetAllStudentWithSameNameAsyncTask extends AsyncTask< String,Void, List<Student> > {

    StudentDao studentDao;

    public GetAllStudentWithSameNameAsyncTask(StudentDao studentDao) {
        this.studentDao = studentDao;
    }

    @Override
    protected List<Student> doInBackground(String... strings) {
        List<Student> students = studentDao.getStudentWithSameName(strings[0]);
        return students;
    }

    @Override
    protected void onPostExecute(List<Student> students) {
        studentsWithSameName = students;
        super.onPostExecute(students);
    }
}

视图模型:

public List<Student> getStudentWithSameName(String studentName) {
    studentsWithSameName = studentRepository.getAllStudentWithSameName(studentName);
    return studentsWithSameName;
}

主活动:

viewModel = ViewModelProviders.of(this).get(StudentViewModel.class);
List<Student> students = viewModel.getStudentWithSameName("Bill");

【问题讨论】:

  • 请显示您如何检索列表的代码:)
  • 也许他发现了这个……zoftino.com/android-persistence-library-room
  • 好吧,不要在 UI 线程上获取数据,这可能会导致 ANR。
  • @Brandon 我添加了代码 sn-p 以便更好地理解。
  • 谢谢@Faisal 成功了!这正是我想要的。

标签: android android-room android-livedata


【解决方案1】:

您需要使用异步(“挂起”)函数,因为数据库调用可能需要很长时间。然后要使用结果,您必须在完成时调用一个代码块,而不是立即运行它。


在我的YourClassDao.kt 中,将fun 更改为suspend fun,并将LiveData&lt;List&lt;YourClass&gt;&gt; 更改为List&lt;YourClass&gt;

// original: this returns a LiveData object
@Query("SELECT * FROM my_table WHERE my_field = :myId")
fun getMyObject(myId: String): LiveData<List<YourClass>>

变成:

// new: this returns a normal object
@Query("SELECT * FROM my_table WHERE my_field = :myId")
suspend fun getMyObject(myId: String): List<YourClass>

要使用数据,您需要启动异步作业来获取数据,然后invokeOnCompletion 使用数据所需的代码。

// using the second (suspend fun) version from above
fun useMyData() {
    val database = AppDatabase.getInstance(context).YourClassDao()  // context could be an activity, for example.

    // start an async job to get the data
    val getDataJob = GlobalScope.async { database.getMyObject("someId") }

    // tell the job to invoke this code when it's done
    getDataJob.invokeOnCompletion { cause ->
        if (cause != null) {
            // error!  Handle that here
            Unit
        } else {
            val myData = getDataJob.getCompleted()

            // ITEM 1
            // ***************************
            // do something with your data
            // ***************************

            Unit  // this is just because the lambda here has to return Unit
        }
    }

    // ITEM 2 - this might happen before ITEM 1
} 

【讨论】:

  • 不推荐使用 GlobalScope 吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-01
  • 1970-01-01
  • 2020-06-24
相关资源
最近更新 更多