如何使用 Coroutines Flow 根据另一个视图中的更改修改一个视图?

How to use Coroutines Flow to modify one view based on the change in another view?

我有两个编辑文本每当我输入一个编辑文本时,我都想发出数据并填充另一个编辑文本。在下面找到我试过的代码

class MainActivity : AppCompatActivity() {

    private var editText : EditText? = null
    private var editText1 : EditText? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val linearLayout = LinearLayout(baseContext)
        linearLayout.orientation = LinearLayout.VERTICAL
        editText = EditText(baseContext)
        editText1 = EditText(baseContext)
        linearLayout.addView(editText)
        linearLayout.addView(editText1)
        setContentView(linearLayout)

        CoroutineScope(Dispatchers.Main).launch {
            sendData().collect{
                editText!!.setText(it)
            }
        }

    }

    private fun sendData()  = flow  {
        editText1?.addTextChangedListener {
            emit(it.toString())
        }


    }.flowOn(Dispatchers.Default)

}

你真的需要为此使用 Flow 吗?

editText?.addTextChangedListener{ editable ->
            editText1.setText(editable.toString())
}

编辑: 由于这只是为了学习目的,所以有机会使用callbackFlow。但是你必须小心在发射后关闭回调:

fun listenTextChange(): Flow<String> = callbackFlow{
   editText.addTextChangeListener{
        offer(it.toString())
   }
   awaitClose{ editText.removeListener() //if there is one or just make the callback null }
}

然后,您可以:

listenTextChange().collect{text -> 
    editText1.setText(text)
}

Kotlin 扩展函数版本:

@ExperimentalCoroutinesApi
val EditText.textFlow: Flow<String>
    get() = callbackFlow {
        val textWatcher = doAfterTextChanged { offer(it.toString()) }
        awaitClose { removeTextChangedListener(textWatcher) }
    }

另一种解决方案如下; 每当您输入 editText 时,TextView 都会更新。

class MainActivity : AppCompatActivity() {

private lateinit var editText: EditText
private lateinit var textView: TextView

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    editText = findViewById(R.id.edit_query)
    textView = findViewById(R.id.text_view)

    lifecycleScope.launch {
        listenTextChange().collect { str ->
            textView.text = str
        }
    }

}

@ExperimentalCoroutinesApi
fun listenTextChange(): Flow<String> = callbackFlow {
    val watcher = object : TextWatcher {
        override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            //
        }

        override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            //
        }

        override fun afterTextChanged(editable: Editable?) {
            trySend(editable.toString())
        }

    }
    editText.addTextChangedListener(watcher)
    awaitClose {
        editText.removeTextChangedListener(watcher)
    }
}

}