Instantiating an Interface Listener in Kotlin
19,370
Solution 1
You can do watchers/listeners like this:
val textView: TextView = this.findViewById(R.id.amountEdit)
val watcher = object : TextWatcher {
override fun afterTextChanged(p0: Editable?) {
val inputAmount = textView.text.toString
val amount = if (!inputAmount.isEmpty()) inputAmount.toDouble() else 0.0
conversionViewModel?.convert(amount)
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
println("before text changed called..")
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
println("text changed..")
}
}
and then:
textView.addTextChangedListener(watcher)
Notice the object in declaring the watcher. Can do the same with a listener.
Solution 2
Also we can use listener without some interface and with default value like:
val someButtonListener: (isChecked: Boolean) -> Unit = {_ -> }
val someButtonListener: (v: View) -> Unit = {_ -> }
Comments
-
Josh Ribeiro almost 2 years
I cannot, for the life of me, instantiate an interface outside of a fragment in Kotlin or Kotlin for Android. It was standard procedure in Java to say something like:
MyInterface mInterfaceListener = new MyInterface(this); mInterfaceListener.invokeSomeGenericMethod();
Note that mInterfaceListener is referring to an Interface, not an onCLickListener or anything like that
How are interfaces instantiated in Kotlin? How do I make a "listener" and trigger an interface's functions?
Below are some attempts in a very simple app I am doing for learning purposes. Notice the variable mPresenterListener which is an Interface
class QuoteActivity : QuoteContract.ViewOps, AppCompatActivity() { private lateinit var vText: TextView private lateinit var vFab: FloatingActionButton private lateinit var mPresenterListener: QuoteContract.PresenterOperations override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) mPresenterListener = this.mPresenterListener vText=findViewById(R.id.main_quote) vFab=findViewById(R.id.main_fab) vFab.setOnClickListener{ mPresenterListener.onQuoteRequested() } } override fun displayQuote(quote: String) { vText.text = quote } }
And my presenter:
class QuotePresenter(private val viewListener: QuoteContract.ViewOps): QuoteContract.PresenterOperations { private lateinit var modelListener: QuoteContract.ModelOperations init { modelListener = this.modelListener } override fun onQuoteRequested() { modelListener.generateQuote() } override fun onQuoteGenerated(quote: String) { viewListener.displayQuote(quote) } }
The interface:
interface QuoteContract { //Methods available to Presenter (Presenter -> View) interface ViewOps{ fun displayQuote(quote: String) } //Ops offered from presenter to view (Presenter->View) interface PresenterOperations { //Presenter->View fun onQuoteRequested() //Presenter->Model fun onQuoteGenerated(quote: String) } //Ops offered from Model to Presenter (Model -> Presenter) interface ModelOperations { fun generateQuote() }
}
-
Josh Ribeiro over 6 yearsOk, so just to wrap my head around your method: Textwatcher is an interface and you are assigning it to a singleton? How would this work in a typical MVP scenario? Thank you for your answer
-
Rob over 6 yearsWhy is it a singleton? it's an instance. This is one of the many great things about Kotlin: you can make instances out of interfaces, as objects.
-
Josh Ribeiro over 6 yearsThe mini-course I had taken defined the Singleton in Kotlin as an Object which can only have one instance of itself. I see Singleton sometimes in dependency injection, so I am not sure if there is some vocabulary overlap. Anyway, thank you for following up with my "answer". Yours is the answer, I just got lost with all the TextView shinnanigans and I wasn't sure if TextWatcher was an interface or some Android library class. Regardless, you helped me out and answered the question: assign it to an object. Much much easier than my solution. Thank you
-
Rob over 6 yearsSure, glad it helped @JoshRibeiro, good on you for wanting to learn the right way to do things. This question caught my eye because when I was learning the new Android Blueprints I had the exact question of how best to adapt the Java approach.