Как я могу использовать обратный вызов в Котлине?

У меня есть View и один CircleShape, который должен показывать тост в этом представлении. И я использую его в основной деятельности. Это мой интерфейс

interface OnClickListenerInterface {
  fun onClick()
}

Это CircleShape (это View in my xml) и прослушиватель в моем представлении. Я хочу реализовать OnClick в своей работе.

 var listener: OnClickListenerInterface? = null

 mCircleShape.setOnClickListener(View.OnClickListener {
      if (listener == null) [email protected]
      listener!!.onClick()
    })

Я знаю, что в Kotlin получатели и сеттеры генерируют автоматику, но как я могу установить слушателя, если он частный. Это код из моей активности, но он не работает

CircleShape.listener  = object :OnClickListenerInterface{
      override fun onClick() {
        ToastUtils.showSuccessMessage(getContext(),"pressed")
      }
    }

Как я должен использовать Callback, onClickListenere в Котлине?

Ответ 1

Более простое решение с использованием лямбды.

Внутри CircleShape.kt объявите лямбда-функцию.

var listener: (()->Unit)? = null
...
// When you want to invoke the listener
listener?.invoke()

Внутри вашей деятельности

mCircleShape.listener = {
    // Do something when you observed a call
}

Ответ 2

На CircleShape.kt.

private listener OnClickListenerInterface? = null
...
fun setOnClickListener(listener: OnClickListenerInterface){
    this.listener = listener
}

О вашей активности

mCircleShape.setOnClickListener(object: CircleShape.OnClickListenerInterface {
    override fun onClick(){ // Do something here
    }
}

Если вы собираетесь использовать лямбда-выражение, вы можете использовать тип функции. Вот как это выглядит на CirclesShapt.kt

fun setOnClickListener(listener: () -> Unit){
   listener() // or you could use optional if the lister is nullable "listener?.invoke()"
}

Так в действии выглядит так.

mCircleShape.setOnClickListener {
  // Do something here
}

Ответ 3

использовать обратные вызовы Kotlin, Я использую их в своих вызовах API для успеха или неудачи использовать

создать перечислимый класс для состояния

enum class APIState(val result: Boolean) {
SUCCESS(true),
FAILURE(false)}

использовать перезвонить в шутку

 private fun fetchFeesList(studentID:String,call:(APIState)->Unit){
 ... do stuff here , and use call(APIState.SUCCESS) or call(APIState.FAILURE) }

при вызове функции fetchFeesList вызывайте ее как

fetchFeesList(studentID){
        val res = it.result
        if(res){
            toast("success")
        }else {
            toast("failure")
        }
    }

for toast("message"), use Anko Lib from GitHub: - https://github.com/Kotlin/anko

Ответ 4

определите функцию следующим образом:

  fun performWork(param1: String, myCallback: (result: String?) -> Unit) {
    // perform some network work
    // on network finished
    myCallback.invoke("result from network")
  }

тогда используйте как:

  performWork("http://..."){ result ->
  //use result
  }

Ответ 5

Прежде всего, вам нужно удалить этот код:

mCircleShape.setOnClickListener(View.OnClickListener {
      if (listener == null) [email protected]
      listener!!.onClick()
    })

Поскольку слушатель сначала всегда имеет значение null, а ваш код всегда возвращается.

var listener: OnClickListenerInterface? = null var listener: OnClickListenerInterface? = null уже является общедоступным (это уровень доступа по умолчанию в Котлине). Поэтому вы можете просто установить его в своей деятельности, когда это необходимо. listener?.onClick() чтобы вызвать его из CircleShape.

Ответ 6

Вы пытались использовать лямбда-выражение? Например, в вашем случае:

mCircleShape.setOnClickListener( 
    { _ -> ToastUtils.showSuccessMessage(context,"pressed") }
)

Или, если вы хотите сделать его более стилем kotlin:

mCircleShape.listener = ( 
    { _ -> ToastUtils.showSuccessMessage(context,"pressed") }
)