https://kotlinlang.org logo
#coroutines
Title
# coroutines
m

Mohamed Ibrahim

03/13/2020, 8:48 PM
I’m trying to create a flow from an EditText change in Android, I’m using
flow {…}
builder, So I’m creating a watcher inside it here is the code, my question is how I clear inner listeners when flow canceled ?
Copy code
fun EditText.textChangesFlow(): Flow<TextViewTextChangeEvent> {
    flow<TextViewTextChangeEvent> {
        val watcher = object : TextWatcher {
            override fun afterTextChanged(s: Editable?) {
                emit(TextViewTextChangeEvent(s.toString()))
            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            }
        }
        addTextChangedListener(watcher)
         //how to call this when flow is canceled or finished
        //removeTextChangedListener(watcher)

    }
}
s

streetsofboston

03/13/2020, 8:51 PM
Add an
awaitClose { … clear inner listeners here … }
at the end of your
flow { … }
lambda:
Copy code
flow<TextViewTextChangedEvent> {
    ...
    ...
    awaitClose { removeTextChangedListener(watcher) }
  }
👍 1
k

kevin.cianfarini

03/13/2020, 8:57 PM
You must use
channelFlow
not
flow
. Within the scope of channelFlow you can use awaitClose. You must also change
emit
to
send
Copy code
channelFlow<TextViewTextChangedEvent> {
    ...
    ...
    awaitClose { removeTextChangedListener(watcher) }
  }
👍 2
m

Mohamed Ibrahim

03/13/2020, 9:03 PM
Do I need to make
textChangesFlow
suspend function, I have a compile error with
send()
and
emit()
k

kevin.cianfarini

03/13/2020, 9:03 PM
The scope inside channel flow should be suspend. So I wouldn't think so
s

streetsofboston

03/13/2020, 9:08 PM
But the callback
afterTextChanged
is not suspend. So yes, either use
offer(…)
or wrap it inside a launch:
launch { send(…) }
.
m

Mohamed Ibrahim

03/13/2020, 9:14 PM
I used
launch{...}
but is it safe to call?
s

streetsofboston

03/13/2020, 9:45 PM
Not sure what you mean by ‘safe’?
But creating Coroutines (using launch or async) is cheap, if you were worrying about that.
t

tseisel

03/14/2020, 8:41 AM
I'd suggest using
callbackFlow
instead of
channelFlow
. While both provide exactly the same behavior,
callbackFlow
makes the intent clearer in this case. Also, since 1.3.4 there is a lint warning with
callbackFlow
that notifies you if you forget about
awaitClose
.
💯 3
d

dekans

03/14/2020, 4:47 PM
212 Views