Круглый индикатор выполнения в JetPack

У меня есть функция, которая извлекает данные из API и отображает эти данные. Я хочу, чтобы на экране отображался круговой индикатор выполнения, пока страница не будет готова.

fun Preview(Number: String) {
    var selected by remember { mutableStateOf<Train?>(null) }
    //var isLoading = remember { mutableStateOf(true) }
    LaunchedEffect(key1 = Unit) {
    //Simulate an API delay
         delay(1000) 
        selected = data from API
    }
 
    if (selected != null) {
       
     
        HorizontalPager(
            state = pagerState,
            modifier = Modifier.fillMaxSize(),
            beyondBoundsPageCount = 2
        )
        { index ->
            selected?.get(index)?.let {
                PagerContent(it)
            }
        }
    } else {
        Column(
            Modifier.fillMaxSize(),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            CircularProgressIndicator(color = Color.Blue)
            Spacer(modifier = Modifier.height(10.dp))
            Text(text = "Loading Please Wait...")
        }
    }
}

Этот код показывает индикатор выполнения, а затем он зависает. Я думаю, подождите, пока PagerContent() загрузится. Я хочу, чтобы он продолжал показывать индикатор выполнения до тех пор, пока PagerContent() не будет загружен/данные не отобразятся на странице.

Кажется, это работает так, как задумано. Можете ли вы убедиться, что приведенный выше код действительно воспроизводит проблему? Убедитесь, что это не вызвано каким-то кодом, который вы не предоставили, например классом Train, как на самом деле рассчитывается selected или PagerContent.

Leviathan 19.05.2024 09:29

Это не вызывает никаких проблем, индикатор выполнения работает нормально, пока выбранное не станет нулевым, затем он какое-то время зависает, а затем страница отображается с данными. Я думаю, что функции PagerContent требуется время для загрузки/отображения данных. Мой вопрос: как я могу проверить, загружен ли PagerContent() или все еще загружается?

Pawandeep Singh 19.05.2024 22:01
0
2
71
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я думаю, вам следует попробовать разделить операторы условий IF и ELSE и проверить.

            if (selected != null) {
                   
                 
                    HorizontalPager(
                        state = pagerState,
                        modifier = Modifier.fillMaxSize(),
                        beyondBoundsPageCount = 2
                    )
                    { index ->
                        selected?.get(index)?.let {
                            PagerContent(it)
                        }
                    }
            }

             if (selected == null) {
                    Column(
                        Modifier.fillMaxSize(),
                        verticalArrangement = Arrangement.Center,
                        horizontalAlignment = Alignment.CenterHorizontally
                    ) {
                        CircularProgressIndicator(color = Color.Blue)
                        Spacer(modifier = Modifier.height(10.dp))
                        Text(text = "Loading Please Wait...")
                    }
            }

Почему вы думаете, что это что-то изменит? Пожалуйста, отредактируйте свой ответ и добавьте пояснение. И пока вы это делаете, пожалуйста, также правильно отформатируйте код и сделайте отступы.

Leviathan 19.05.2024 20:23

Не работает, такой же как у меня был.

Pawandeep Singh 19.05.2024 21:56
Ответ принят как подходящий

Пользовательский интерфейс работает в одном потоке — главном потоке. Вы можете запускать сопрограммы, но, как правило, они не могут вызывать составные функции. Это также означает, что пользовательский интерфейс не может быть создан асинхронно. Поэтому вы можете либо отобразить кадр анимации, либо создать какую-то другую часть пользовательского интерфейса, но не то и другое одновременно. Если создание какого-либо элемента пользовательского интерфейса занимает слишком много времени, следующий кадр анимации не может быть выполнен достаточно быстро, поэтому анимация кажется «зависающей».

Настоящий вопрос, который вы должны задать себе, заключается в том, почему PagerContent выполнение занимает так много времени, что это заметно.

Функции Compose предназначены для очень быстрого выполнения, поскольку они выполняются каждый раз, когда происходит рекомпозиция. Рекомпозиции вообще могут происходить так часто, как каждый кадр, обычно не менее 60 раз в секунду. «Может произойти» означает, что это худший случай, и обычно у вас будет гораздо меньше рекомпозиций. Тем не менее, вам нужно, чтобы ваши компонуемые функции выполнялись как можно быстрее, чтобы избежать подобных зависаний, с которыми вы столкнулись.

Что вам нужно сделать, так это сделать PagerContent быстрее. Поскольку вы не поделились кодом PagerContent, мы можем только предполагать, почему его выполнение занимает так много времени. Возможные причины:

  • Отображение больших объемов данных, даже если большая их часть находится за кадром. Примером может служить длинный список элементов, отображаемый в прокручиваемом столбце. Каждый элемент необходимо будет создать, даже если большинство из них будет за кадром. В этом случае решением было бы использовать LazyColumn, который создает только те элементы, которые действительно видимы.
  • Выполнение длительных операций. Это могут быть сложные вычисления, которые потребляют много процессорного времени, или множество быстрых операций, таких как итерация/сопоставление очень длинного списка. Оба должны быть перемещены из основного потока в модель представления и выполнены в диспетчере по умолчанию. Другим источником длительных операций могут быть операции ввода-вывода, такие как доступ к базе данных или даже сетевой запрос. Их следует переместить в диспетчер ввода-вывода. Однако во всех этих случаях пользовательский интерфейс должен подключаться только после того, как результат станет доступен модели представления, чтобы ему не приходилось ждать и не блокировать основной поток.

Этот список не является исчерпывающим, но суть вы, вероятно, поняли: переместите все, что не имеет прямого отношения к созданию элементов пользовательского интерфейса (которые должны выполняться в основном потоке), из PagerContent в модель представления, одновременно выполняя это в другом, более соответствующий диспетчер.

Когда PagerContent будет достаточно быстрым и время его выполнения больше не будет заметно, проблема, которую вы описали в своем вопросе, также исчезнет.

Другие вопросы по теме