没有LiveData的房间

问题描述 投票:3回答:3

我正在尝试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);
    }
}

ViewModel:

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

MainActivity:

viewModel = ViewModelProviders.of(this).get(StudentViewModel.class);
List<Student> students = viewModel.getStudentWithSameName("Bill");
android android-room android-livedata
3个回答
0
投票
class WordViewModel(application: Application) : AndroidViewModel(application) { private var parentJob = Job() private val coroutineContext: CoroutineContext get() = parentJob + Dispatchers.Main private val scope = CoroutineScope(coroutineContext) private val repository: WordRepository val allWords: LiveData<List<Word>> init { val wordsDao = WordRoomDatabase.getDatabase(application).wordDao() repository = WordRepository(wordsDao) allWords = repository.allWords } fun insert(word: Word) = scope.launch(Dispatchers.IO) { repository.insert(word) } override fun onCleared() { super.onCleared() parentJob.cancel() } }

IMHO:比AsyncTask好。

您可以跟随Google的codelabs并学习如何使用Kotlin Coroutines


0
投票

在我的YourClassDao.kt中:


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

成为:

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

就我而言,我像这样使用函数:

// using the second (suspend fun) version from above
fun useMyData() {
    val database = AppDatabase.getInstance(context).YourClassDao()  // context could be an activity, for example.
    val getDataJob = GlobalScope.async { database.getMyObject("someId") }
    getDataJob.invokeOnCompletion { cause ->
        if (cause != null) {
            //something happened and the job didn't finish successfully.  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
}

请记住,这仍然适用于异步数据,因此我代码中的ITEM 2可能在ITEM 1之前发生。


0
投票
© www.soinside.com 2019 - 2024. All rights reserved.