Котлин: Как отложить код в Android, не останавливая пользовательский интерфейс - PullRequest
0 голосов
/ 24 января 2019

Я пытаюсь отложить код в Kotlin. Я пробовал

Thread.sleep(1000)

Но он замораживает пользовательский интерфейс.

Кто-нибудь знает, почему это происходит, и как отложить, не замораживая пользовательский интерфейс

Ответы [ 5 ]

0 голосов
/ 24 января 2019

Пояснение:

Thread.sleep(1000) работает в потоке пользовательского интерфейса, который отвечает за отображение приложения и его адаптацию.

Вызов sleep сделает его не отвечающим на 1 секунду, потому что он блокирует дальнейшее выполнение.

Что делать вместо:

Хороший способ обработки долгосрочных задач - AsyncTask, поскольку он проводит четкое различие между потоком пользовательского интерфейса и рабочим потоком.

AsyncTask позволяет правильно и легко использовать поток пользовательского интерфейса. Этот класс позволяет выполнять фоновые операции и публиковать результаты на Поток пользовательского интерфейса без необходимости манипулировать потоками и / или обработчиками.

Пример:

class LongRunningTask : AsyncTask<Unit, Unit, String>() {

     override fun doInBackground(vararg units: Unit): String {

         // runs on separate thread

         Thread.sleep(1000) // some long running operation

         return "Hello"
     }

     override fun onPostExecute(result: String) {
        // This runs on the main thread again
        // and views can be updated with the result
     }
 }

Вы можете использовать это так:

LongRunningTask().execute()
0 голосов
/ 24 января 2019

Что пошло не так

Использование Thread.sleep(...)

Thread.sleep заставляет текущий поток приостанавливать выполнение на указанный период. Это эффективное средство предоставления процессорного времени доступным другим потокам приложения или другим приложениям, которые могут работать в компьютерной системе.

Для разъяснения OP (Оригинальный постер / Аскер):

Он замораживает интерфейс, кто-нибудь знает, почему это происходит?

Как упоминалось выше из официальной документации Java, вы испытываете некоторое зависание в пользовательском интерфейсе, потому что вы вызвали его в Main Thread .

Основной поток или, если вы делаете свои вещи в Android, его часто называют Пользовательский интерфейс :

На платформе Android приложения по умолчанию работают в одном потоке. Этот поток называется потоком UI . Это часто называют так, потому что этот единственный поток отображает пользовательский интерфейс и прослушивает события, которые происходят, когда пользователь взаимодействует с приложением.

Без использования многопоточных API (таких как Runnable, Coroutines, RxJava) вы автоматически будете вызывать Thread.sleep(1000) в потоке пользовательского интерфейса , поэтому вы вы испытываете "UI Freezing" опыт, потому что другие UI Operations заблокированы от доступа к потоку, так как вы вызвали приостановку на нем.

А как отложить без зависания интерфейса?

Используйте всю мощь доступных API для многопоточности, поэтому лучше начать со следующих опций:

1. Runnable

В Java

// Import
import android.os.Handler;

// Use
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
  @Override
  public void run() {
     // do something after 1000ms
  }
}, 1000);

В Котлине

// Import
import android.os.Handler;

// Use
val handler = Handler()
handler.postDelayed({
     // do something after 1000ms
}, 1000)

2. Котлин сопрограммы

// Import
import java.util.*
import kotlin.concurrent.schedule

// Use
Timer().schedule(1000){
    // do something after 1 second
}

3. RxJava

// Import
import io.reactivex.Completable
import java.util.concurrent.TimeUnit

// Use
Completable
     .timer(1, TimeUnit.SECONDS)
     .subscribeOn(Schedulers.io()) // where the work should be done
     .observeOn(AndroidSchedulers.mainThread()) // where the data stream should be delivered
     .subscribe({
          // do something after 1 second
     }, {
          // do something on error
     })

В настоящее время RxJava является одним из трех способов многопоточности и обработки огромного количества потоков данных в вашем приложении. Но если вы только начинаете, хорошо бы сначала опробовать основы.

Ссылки

0 голосов
/ 24 января 2019

Вы можете использовать объект-обработчик https://developer.android.com/reference/android/os/Handler.

val handler = Handler()
val runnable = Runnable {
    // code which will be delayed  
}

handler.postDelayed(runnable, 1000)

1000 - время в миллисекундах, вы должны заменить его своим значением.

0 голосов
/ 24 января 2019

Thread.sleep(1000);

Заставляет текущий выполняющийся поток спать (временно прекращается выполнение) за указанное количество миллисекунд, [...]

см. https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#sleep(long)

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

В чистом котлине вы должны использовать сопрограмму :

import kotlinx.coroutines.*

fun main() {
    GlobalScope.launch { // launch new coroutine in background and continue
        delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
        println("World!") // print after delay
    }
    println("Hello,") // main thread continues while coroutine is delayed
    Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
}

Если вы программируете приложение для Android, вы можете использовать Handler и Androidx для особенно приятного синтаксиса:

Handler().postDelayed( 1000 ) { doSomething() }
0 голосов
/ 24 января 2019

Если вы не хотите заморозить пользовательский интерфейс, вам нужно выполнить свой код из MainThread .
Существует множество способов сделать это.Некоторые примеры:

Тема

Thread {
    Thread.sleep(1000)
    // Your code
}.start()

Rx

Вам нужно https://github.com/ReactiveX/RxJava

Flowable.timer(1000, TimeUnit.MILLISECONDS)
    .subscribeOn(AndroidSchedulers.mainThread())
    .subscribe { 
        // Your code
    }

Котлин сопрограмма

GlobalScope.launch { // launch new coroutine in background and continue
    delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
    println("World!") // print after delay
}

ссылка: https://kotlinlang.org/docs/reference/coroutines-overview.html

Документация:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...