Jika Anda melakukan tindakan jangka panjang di thread utama, Anda berisiko mengalami ANR crash sebuah>.
Tata letak Anda untuk setiap fragmen harus memiliki tampilan pemuatan yang terlihat pada awalnya, dan tampilan data Anda. Sesuatu seperti ini:
(bukan kode)
FrameLayout
loading_view (can show a progress spinner or something, size is match parent)
content_view (probably a RecyclerView, initial visibility=GONE, size is match parent)
/FrameLayout
Anda perlu melakukan tindakan jangka panjang pada thread latar belakang atau coroutine, lalu menukar visibilitas kedua tampilan ini saat data siap ditampilkan di UI.
Anda tidak boleh menangani pemuatan data secara langsung dalam kode Fragmen Anda, karena Fragmen adalah pengontrol UI. Library Android Jetpack menyediakan kelas ViewModel untuk tujuan ini. Anda akan menyiapkan ViewModel Anda seperti ini. Dalam contoh ini, MyData bisa berupa apa saja. Dalam kasus Anda, kemungkinan besar itu adalah Daftar atau Kumpulan sesuatu.
class MyBigDataViewModel(application: Application): AndroidViewModel(application) {
private val _myBigLiveData = MutableLiveData<MyData>()
val myBigLiveData: LiveData<MyData>() = _myBigLiveData
init {
loadMyBigData()
}
private fun loadMyBigData() {
viewModelScope.launch { // start a coroutine in the main UI thread
val myData: MyData = withContext(Dispatchers.Default) {
// code in this block is done on background coroutine
// Calculate MyData here and return it from lambda
// If you have a big for-loop, you might want to call yield()
// inside the loop to allow this job to be cancelled early if
// the Activity is closed before loading was finished.
//...
return@withContext calculatedData
}
// LiveData can only be accessed from the main UI thread so
// we do it outside the withContext block
_myBigLiveData.value = myData
}
}
}
Kemudian di fragmen Anda, Anda mengamati data langsung untuk memperbarui UI ketika sudah siap. Di bawah ini menggunakan perpustakaan fragment-ktx
, yang perlu Anda tambahkan ke proyek Anda. Anda pastinya harus membaca dokumentasi di ViewModel.
class MyFragment: Fragment() {
// ViewModels should not be instantiated directly, or they won't be scoped to the
// UI life cycle correctly. The activityViewModels delegate handles instantiation for us.
private val model: MyBigDataViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
model.myBigLiveData.observe(this, Observer<MyData> { myData ->
loading_view.visibility = View.GONE
content_view.visibility = View.VISIBLE
// use myData to update the view content
})
}
}
person
Tenfour04
schedule
28.01.2020