Chcę mieć niestandardową klasę klawiatury, która ma różne przyciski. Ta klasa zaimplementuje odbiornik onClick, gdy każdy przycisk zostanie wywołany, ale chcę, aby inna klasa obsługiwała to zdarzenie. Na przykład:
class Keyboard {
Button A
Button B
...
fun onClick() {
// forward this action to the class that contains me
}
}
class MainActivity {
val keyboard = Keyboard()
keyboard.onClickListener {
// handle the click events
}
}
Jak do tego podejść?
2 odpowiedzi
Jeśli Twoim celem jest komunikacja między MainActivity
a Keyboard
, wtedy wystarczy wywołanie zwrotne. Możesz to zaimplementować w ten sposób:
typealias KeyboardCallback = (Button) -> Unit
// Do not recommend doing this, it's for the example only
// It's probably better parsing the keyboard input as Char or Int
enum class Button {
A, B, C, D
}
class Keyboard {
private var callback : KeyboardCallback? = null
fun onKeyPressedListener(listener: KeyboardCallback) {
callback = listener
}
fun onClick(button: Button) {
// forward this action to the class that contains me
callback?.invoke(button)
}
}
class MainActivity {
val keyboard = Keyboard()
keyboard.onKeyPressedListener { key: Button ->
// parse buttons here
}
// Somewhere else (Will call the callback)
keyboard.onClick(Button.A)
}
Ale jeśli chcesz słuchać klawiatury z wielu miejsc, to ta implementacja nie zadziała, ponieważ jak tylko zarejestrujesz drugie wywołanie zwrotne, pierwsze z nich się nieświeży (tracisz do niego odniesienie, ponieważ zmienna callback
może pomieścić tylko jednego słuchacza), możesz zobaczyć ten problem tutaj.
Jeśli jest to w porządku w przypadku Twojej implementacji, zrób to (jest to znane jako wzorzec polecenia ** ). Jeśli tak nie jest, musisz wdrożyć Observable / Observer Pattern, który bardziej przypomina to:
typealias KeyboardCallback = (Button) -> Unit
// Do not recommend doing this, it's for the example only
// It's probably better parsing the keyboard input as Char
enum class Button {
A, B, C, D
}
class Keyboard {
private val listeners = ArrayList<KeyboardCallback>()
fun onKeyPressedListener(listener: KeyboardCallback) {
callback.add(listener)
}
fun onClick(button: Button) {
// forward this action to the class that contains me
for (callback in listeners) {
callback(button)
}
}
}
class MainActivity {
val keyboard = Keyboard()
keyboard.onKeyPressedListener { key: Button ->
// parse buttons here
}
keyboard.onKeyPressedListener { another: Button ->
// added another listener
}
// Somewhere else (Will call the callback)
keyboard.onClick(Button.A)
}
Zrobiłem prosty przykład dla obserwowalnych na tym kotlin plac zabaw.
** Cóż, niezupełnie, jest to jego uproszczona wersja, ponieważ wzorzec polecenia jest zaimplementowany przy użyciu interfejsu i klasy do reprezentowania „polecenia / wywołania zwrotnego”, a ta klasa może przechowywać dowolny stan, czego nie może używać wskaźnik funkcji.
- Utwórz atrybut
clickListener
w klasie Keyboard - Utwórz metodę ustawiającą dla tego atrybutu
- W swojej metodzie onCLick w
Keyboard
wywołaj po prostuclickListener?.onClick(buttonClicked)
, gdziebuttonClicked
to przycisk na klawiaturze, który został kliknięty - W swoim
MainActivity
ustaw nasłuchiwanie i obsłuż zdarzenia clickEvent
Przykład:
class Keyboard {
private var clickListener: View.OnClickListener? = null
fun setListener(listener: View.OnClickListener) {
clickListener = listener
}
fun onClick() {
clickListener?.onClick(buttonClicked) // pass button which was clicked
}
}
class MainActivity {
private val keyboard = Keyboard()
init {
keyboard.setListener(View.OnClickListener {
//do something
//it -> button which was clicked
})
}
}
Podobne pytania
Nowe pytania
android
Android to mobilny system operacyjny Google, używany do programowania lub tworzenia urządzeń cyfrowych (smartfony, tablety, samochody, telewizory, Wear, Glass, IoT). W przypadku tematów związanych z Androidem użyj tagów specyficznych dla Androida, takich jak android-intent, android-activity, android-adapter itp. W przypadku pytań innych niż programowanie lub programowanie, ale związanych ze strukturą Androida, użyj tego linku: https: // android.stackexchange.com.