Как изменить переменные вне их области видимости в kotlin? - PullRequest
1 голос
/ 05 августа 2020

Я понимаю, что в Kotlin нет таких вещей, как «нелокальные переменные» или «глобальные переменные». Я ищу способ изменить переменные в другой «области» в Kotlin с помощью функции ниже :

class Listres(){
var listsize = 0
fun gatherlistresult(){
    

    var listallinfo = FirebaseStorage.getInstance()
                                     .getReference()
                                     .child("MainTimeline/")
                                     .listAll()
    listallinfo.addOnSuccessListener {
        listResult -> listsize += listResult.items.size
    }
                
    
}
}

значение listize всегда равно 0 (регистрация результата изнутри области .addOnSuccessListener возвращает 8), поэтому очевидно, что переменная listsize не изменяется. Я видел много разных сообщений об этом topi c на других сайтах, но ни один из них не подходит для моего использования.

Я просто хочу изменить listsize внутри .addOnSuccessListener обратного вызова

Ответы [ 2 ]

1 голос
/ 05 августа 2020

Этот метод всегда будет возвращать 0, так как прослушиватель addOnSuccessListener() будет вызван после завершения выполнения метода. addOnSuccessListener() - это метод обратного вызова для операции asynchronous, и вы получите значение только в случае успеха.

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

class Demo {

 fun registerListResult() {
     var listallinfo = FirebaseStorage.getInstance()
                                     .getReference()
                                     .child("MainTimeline/")
                                     .listAll()
    listallinfo.addOnSuccessListener {
        listResult -> listsize += listResult.items.size
        processResult(listsize)
    }
    listallinfo.addOnFailureListener {
        // Uh-oh, an error occurred!
     }
 }

 fun processResult(listsize: Int) {
    print(listResult+"") // you will get the 8 here as you said
 }
}
0 голосов
/ 05 августа 2020

То, что вы ищете, - это способ связать некоторую асинхронную обработку с синхронным контекстом. Если возможно, обычно лучше (на мой взгляд) придерживаться одной модели (syn c или asyn c) во всей базе кода.

Тем не менее, иногда эти обстоятельства находятся вне нашего контроля. Один из подходов, который я использовал в аналогичных ситуациях, включает введение BlockingQueue в качестве канала данных для передачи данных из контекста asyn c в контекст syn c. В вашем случае это может выглядеть примерно так:

class Demo {
  var listSize = 0

  fun registerListResult() {
    val listAll = FirebaseStorage.getInstance()
        .getReference()
        .child("MainTimeline/")
        .listAll()

    val dataQueue = ArrayBlockingQueue<Int>(1)

    listAll.addOnSuccessListener { dataQueue.put(it.items.size) }

    listSize = dataQueue.take()
  }
}

Ключевые моменты:

  • существует вариант блокировки интерфейса Queue, который будет использоваться для данные конвейера из контекста asyn c (слушателя) в контекст syn c (код вызова)
  • данные put() в очереди в OnSuccessListener
  • вызывающем код вызывает метод очереди take(), который заставит этот поток блокироваться до тех пор, пока не будет доступно значение

Если это не сработает для вас, надеюсь, это, по крайней мере, вдохновит на некоторые новые мысли!

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