как сделать загрузку в Kotlin - PullRequest
0 голосов
/ 27 января 2020

my MainActivity содержит ViewPager, который загружает 4 фрагмента, каждый фрагмент должен загружать множество данных с сервера.

, поэтому, когда мое приложение хочет запускаться в первый раз, это почти занимает более 3 секунд а в другое время (например, если вы выходите из приложения, но не очищаете его из окна «недавно появившееся приложение» и снова открываете его), это занимает почти 1 секунду.

во время загрузки показывает белый экран .

есть ли какой-нибудь способ вместо отображения белого экрана, пока данные не будут готовы, я показываю свое собственное изображение? что-то вроде страницы spla sh?

1 Ответ

1 голос
/ 28 января 2020

Если вы выполняете длительные действия в главном потоке, вы рискуете получить 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
        })
    }
}
...