2016-04-07 9 views
14

Dlaczego Kotlin narzeka na ten temat:Zmienna „runnable” muszą być inicjowane

class MyActivity : Activity { 
    private var handler:Handler = Handler() 

    private var runnable: Runnable = Runnable { 
    /* Do something very important */ 
    handler.postDelayed([email protected], 5000) 
    } 
} 

Kompilator narzeka, że ​​Variable 'runnable' must be initialized w kolejce były to ponownie wysłane przez przewodnika. To działa w zwykły Java:

private Handler handler = new Handler(); 

private Runnable runnable = new Runnable() { 
    @Override 
    public void run() { 
     handler.postDelayed(runnable, 5000); 
    } 
}; 
+1

Nie jesteś zaniepokojony, że jest cykliczna odniesienie lub coś? – AndroidEx

+0

Czy powinienem być? Pomysł, że to Runnable powinno być wykonywane co 5s. Czy może brakuje mi czegoś oczywistego ?! – GeneralOfTheFelixLegions

Odpowiedz

13

Kotlin uważa właściwość niezainicjowanej do końca jego inicjatora, dlatego nie może być stosowany wewnątrz własnej inicjatora, nawet w lambdas. Ta semantyka jest podobna do ograniczenia local variable usage inside its initializer.

Istnieje kilka obejścia:

  • Zastosowanie object expression który pozwala odwołać this deklarowanej obiektu:

    private var runnable: Runnable = object : Runnable { 
        override fun run() { 
         /* Do something very important */ 
         handler.postDelayed(this, 5000) 
        } 
    } 
    

    To działa dobrze tylko dla interfejsów jako zamiennik lambdas i nie jest bardzo całkiem całkiem.

  • Zastosowanie lateinit var lub delegated property z Delegates.notNull():

    private lateinit var runnable: Runnable 
    init { 
        runnable = Runnable { 
         /* Do something very important */ 
         handler.postDelayed(runnable, 5000) 
        } 
    } 
    

    Ten sam inicjator będzie współpracować z tej deklaracji:

    private var runnable: Runnable by Delegates.notNull() 
    
  • Wdrożenie i wykorzystanie self-reference for initializers na własną rękę:

    class SelfReference<T>(val initializer: SelfReference<T>.() -> T) { 
        val self: T by lazy { 
         inner ?: throw IllegalStateException("Do not use `self` until initialized.") 
        } 
    
        private val inner = initializer() 
    } 
    
    fun <T> selfReference(initializer: SelfReference<T>.() -> T): T { 
        return SelfReference(initializer).self 
    } 
    

    a następnie można napisać coś

    private var runnable: Runnable = selfReference { 
        Runnable { 
         /* Do something very important */ 
         handler.postDelayed(self, 5000) 
        } 
    } 
    
+0

Dzięki za postawienie mnie na właściwej drodze. – tango24

1

Można również użyć

private var runnable: Runnable = Runnable { 
    /* Do something very important */ 
    handler.postDelayed(runnable(), 5000) 
} 

private fun runnable() = runnable 
+0

Zamiast funkcji można również użyć właściwości tylko do odczytu: 'private val runnableCopy get() = runnable' – Heinrich

Powiązane problemy