0

In Android, I have a ListAdapter that I'm passing callbacks to using Kotlin's lambda notation.

For instance, the ListAdapter has:

var clickCallback = { _: Long  -> Unit }

Which gets set in the Fragment calling the ListAdapter with:

mAdapter.clickCallback = {id: Long -> selectItem(id)}

This Fragment function selectItem(id: Long) then gets called inside the ListAdapter with:

clickCallback(item.id) 

But what if that passed function selectItem() returned a value, such as a LiveData, and what if I wanted to call that function and observe that LiveData from inside the adapter? I cannot for the life of me figure out how to pass such a function, so that the callback function inside the ListAdapter can be observed.

This doesn't even come close to working, but hopefully it should give you an idea of the sort of solution I'm looking for:

var clickCallback:LiveData<String> = { _: Long  -> Unit?? }
....
clickCallback(item.id).observe(holder.ItemView, Observer { answerString -> 
    doSomethingTo(answerString)
})

Bonus points if you know how to get the viewLifecycleOwner inside a ListAdapter. I'm just guessing it's the holder.ItemView.

Thanks!

John

1
  • Don't know what you want to do with creating a lambda with {} but Probably you wanted to do: clickCallback: (Long) -> LiveData<String>. Commented Jun 21, 2020 at 14:33

1 Answer 1

2

Creating a callback which returns an object is simple. Just use next syntax for lambda type:

var callback: (([Params]) -> ReturnType)? = null

And the code is:

var clickCallback: ((Long) -> LiveData<String>)? = null

clickCallback?.invoke(item.id)?.observe(holder.ItemView, Observer { answerString ->
    doSomethingTo(answerString)
})

If you want callback with default implementation it will be:

var clickCallback: (Long) -> LiveData<String> = { _: Long  -> MutableLiveData() }

clickCallback(item.id).observe(holder.ItemView, Observer { answerString ->
    doSomethingTo(answerString)
})

Bonus points if you know how to get the viewLifecycleOwner inside a ListAdapter. I'm just guessing it's the holder.ItemView.

It can be achieved by passing viewLifecycleOwner as a constructor parameter:

    // adapter definition
    class YourAdapter(private val lifecycleOwner: LifecycleOwner) ...
    
    // passing viewLifecycleOwner as constructor parameter
    val adapter = YourAdapter(viewLifecycleOwner)

Now you can access lifecycleOwner property inside YourAdapter.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Sergey, that answer works perfectly. May I ask, why do you use MutableLiveData() rather than LiveData<String> in the lambda you describe as the "default implementation"? It works, but I don't understand what's going on.
In the default implementation you need to return something of type LiveData, we can't create an instance of LiveData itself bcz it is abstract, so I used MutableLiveData.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.