Если вы выполняете длительные действия в главном потоке, вы рискуете получить ANR cra sh.
В вашем макете для каждого фрагмента должно быть представление загрузки, которое изначально видны и ваши данные просмотра. Примерно так:
( не код )
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
Необходимо выполнить длительное действие в фоновом потоке или сопрограмме, а затем поменять местами видимость эти два представления, когда данные готовы к отображению в пользовательском интерфейсе.
Вы не должны напрямую обрабатывать загрузку данных в коде фрагмента, поскольку Fragment является контроллером пользовательского интерфейса. Для этой цели библиотеки 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
})
}
}