Kotlin: завернутый в эталонный объект для изменения при захвате в замыкании - PullRequest
0 голосов
/ 09 января 2019

Я реализую Firebase на Android с помощью kotlin.

Поскольку значение FirebaseInstanceId.getInstance().token ограничено, я использую следующую функцию внутри объекта-компаньона моего MyFirebaseMessageService класса, чтобы получить токен:

companion object
{
  fun grabFcmToken():String?
  {
    var s:String?=null
    FirebaseInstanceId.getInstance().
    instanceId.addOnCompleteListener {task ->
    if (task.isSuccessful)
     {
        s=task.result!!.token
        Log.i("token used is ", s)
     }
     else
      {
        throw Exception("Can't get firebase token")
      } 
    }
    Log.i("To be returned token ", s)
    return s
  }
}

Android Studio выделяет s как Wrapped into a reference object to be modified when captured in a closure

После выполнения grabFcmToken() первый журнал успешно распечатывает токен, но второй журнал имеет java.lang.NullPointerException: println needs a message, указывающий, что s имеет значение null, и, следовательно, его значение не изменяется.

как мне изменить s так, чтобы захваченный токен отражался в нем?

1 Ответ

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

Дело в том, что первый журнал находится внутри слушателя для асинхронного . задача. Так что, вероятно, это происходит так:

  1. Звоните grabFcmToken()
  2. FirebaseInstanceId.getInstance().instanceId называется. Здесь начинается задача получить instanceId. Таким образом, вы также вставили слушателя. Поскольку это асинхронная задача, коду не нужно ждать, поэтому он продолжается.
  3. Log.i("To be returned token ", s) работает там, где s равно null. NPE здесь.

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

companion object {
        fun requestPushToken(): Task<InstanceIdResult> {
            return FirebaseInstanceId.getInstance().instanceId
        }
}

Затем позвоните из любого нужного вам класса:

class SampleActivity: AppCompatActivity(){

    YourAppService.requestPushToken().addCompleteListener { task ->
        if (task.isSuccessful){
            // TODO: Handle
        } else {
            // TODO: Handle
        }
    }

}
...