Если вы выполняете длительные действия в основном потоке, вы рискуете получить сбой ANR а>.
Ваш макет для каждого фрагмента должен иметь вид загрузки, который изначально виден, и ваш вид данных. Что-то вроде этого:
(не код)
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
Вам нужно выполнить длительное действие в фоновом потоке или сопрограмме, а затем поменять местами видимость этих двух представлений, когда данные готовы для отображения в пользовательском интерфейсе.
Вы не должны напрямую обрабатывать загрузку данных в коде фрагмента, поскольку фрагмент является контроллером пользовательского интерфейса. Библиотеки Android Jetpack предоставляют для этой цели класс ViewModel. Вы бы настроили свою ViewModel примерно так. В этом примере MyData может быть любым. В вашем случае это, скорее всего, список или набор чего-то.
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
}
}
}
Затем в своем фрагменте вы наблюдаете за живыми данными, чтобы обновить пользовательский интерфейс, когда он будет готов. Ниже используется библиотека fragment-ktx
, которую вам нужно добавить в свой проект. Вам обязательно стоит прочитать документацию по 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