---
# System prepended metadata

title: Handle One-Time Events with Kotlin's Channels實際應用
tags: [flow, channel, Android, kotlin]

---

# Handle One-Time Events with Kotlin's Channels實際應用

* 參考[Handle One-Time Events with Kotlin's Channels](/R-4QS8v_RL6xcGY5OKpa0w)
* 與[Firebase with Android Studio part-14 : Firebase cloud storage upload](/fqJy3Q9OTASIwE0FwGIdrA)

### UI
* 這裡只拿上傳圖片來實作
![](https://i.imgur.com/YA3b0Gi.png)


### 關鍵程式碼
* 底下是MainActivity，透過按鈕執行上傳圖片的function
* collect flow的值做對應的動作
```kotlin=
//使用by viewModels()需搭配implementation "androidx.activity:activity-ktx:1.2.3"
private val viewModel: MainViewModel by viewModels()


lifecycleScope.launchWhenStarted {
            viewModel.uiStates.collect {
                when (it) {
                    is MainViewModel.MyEvent.Success -> {
                        findViewById<ProgressBar>(R.id.progressBar).isVisible = false
                        Toast.makeText(this@MainActivity, "成功上傳圖片", Toast.LENGTH_LONG).show()
                    }
                    is MainViewModel.MyEvent.ErrorEvent -> {
                        findViewById<ProgressBar>(R.id.progressBar).isVisible = false
                        Toast.makeText(this@MainActivity, it.message, Toast.LENGTH_LONG).show()
                    }
                    is MainViewModel.MyEvent.UpLoading -> {
                        findViewById<ProgressBar>(R.id.progressBar).isVisible = true
                    }
                }
            }
        }

        findViewById<Button>(R.id.bt_upload).setOnClickListener {
            viewModel.uploadImageToStorage(curFile, "myImage")
        }
```

* 底下是viewModel
```kotlin=
class MainViewModel : ViewModel() {

    private val imageRfe = Firebase.storage.reference

    private val _uiStates = Channel<MyEvent>()
    val uiStates: Flow<MyEvent> = _uiStates.receiveAsFlow()

    fun uploadImageToStorage(curFile: Uri?, fileName: String) = viewModelScope.launch {
        try {
            curFile?.let {
                _uiStates.send(MyEvent.UpLoading)
                imageRfe.child("images/$fileName").putFile(it).await()
                _uiStates.send(MyEvent.Success)
            }
        } catch (e: Exception) {
           _uiStates.send(MyEvent.ErrorEvent("${e.message}"))
        }
    }

    sealed class MyEvent {
        object Success : MyEvent()
        data class ErrorEvent(val message: String) : MyEvent()
        object UpLoading : MyEvent()
    }
}
```

###### tags: `channel` `flow` `kotlin` `Android`