State Flow และ Shared Flow ใน Kotlin
โฟลว์ของรัฐ
StateFlowเป็นโฟลว์ที่สามารถสังเกตได้ของผู้ถือสถานะซึ่งปล่อยการอัปเดตสถานะปัจจุบันและสถานะใหม่ไปยังตัวรวบรวม- SharedFlow ที่แสดงถึงสถานะแบบอ่านอย่างเดียวด้วยค่าข้อมูลที่อัปเดตได้ค่าเดียวที่ส่งการอัปเดตค่าไปยังตัวรวบรวม
- State Flow ได้รับการออกแบบให้เป็นเวอร์ชันที่มีประสิทธิภาพและง่ายขึ้นของไลบรารี Flow ที่มีอยู่ของ Kotlin โดยมีข้อแตกต่างที่สำคัญคือมันแทนค่าเดียวที่สามารถอัปเดตเมื่อเวลาผ่านไป ในขณะที่ Flow แสดงถึงลำดับของค่า
- โฟลว์สถานะใช้ไวยากรณ์ที่คล้ายกันกับโฟลว์ แต่แทนที่จะปล่อยสตรีมของค่า โฟลว์จะแสดงค่าเดียวที่สามารถอัปเดตได้โดยใช้
valueคุณสมบัติ การเปลี่ยนแปลงค่านี้จะเผยแพร่โดยอัตโนมัติไปยังผู้สังเกตการณ์ทั้งหมดของโฟลว์สถานะ - โฟลว์สถานะเป็น โฟลว์ ที่ร้อนแรงเนื่องจากอินสแตนซ์ที่ใช้งานอยู่นั้นมีอยู่อย่างเป็นอิสระจากการมีอยู่ของคอลเลคเตอร์
- A
StateFlowจะทำงานและอยู่ในหน่วยความจำเสมอ และจะมีสิทธิ์สำหรับการรวบรวมขยะก็ต่อเมื่อไม่มีการอ้างอิงถึงมันจากรูทของการรวบรวมขยะเท่านั้น - โฟลว์สถานะที่ไม่แน่นอนถูกสร้างขึ้นโดยใช้
MutableStateFlow(value)ฟังก์ชันคอนสตรัคเตอร์ด้วยค่าเริ่มต้น - เมธอดโฟลว์สถานะทั้งหมดปลอดภัยต่อเธรดและสามารถเรียกใช้ได้อย่างปลอดภัยจากคอร์รูทีนพร้อมกันโดยไม่ต้องซิงโครไนซ์ภายนอก
ขั้นตอนที่ 1: สร้างคลาสโมเดล
data class User(val id: Int, val name: String, val email: String)
class UserRepository {
suspend fun getUserById(userId: Int): User {
// make API call to fetch user data
val response = // make API call here
return response.toUser() // convert API response to User object
}
}
class UserViewModel(private val repository: UserRepository) : ViewModel() {
private val _user = MutableStateFlow<User?>(null)
val user: StateFlow<User?> = _user
fun getUserById(userId: Int) = viewModelScope.launch {
_user.value = repository.getUserById(userId)
}
}
class UserFragment : Fragment() {
private val viewModel: UserViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val userId = arguments?.getInt("userId") ?: throw IllegalArgumentException("userId is required")
viewModel.getUserById(userId)
viewModel.user.onEach { user ->
userTextView.text = user?.name ?: "Loading..."
emailTextView.text = user?.email ?: ""
}.launchIn(viewLifecycleOwner.lifecycleScope)
}
}
โฟลว์ที่ใช้ร่วมกัน
ใน Kotlin a SharedFlowเป็นโฟลว์ประเภทหนึ่งที่อนุญาตให้ตัวรวบรวมหลายตัวรับค่าที่ปล่อยออกมาจากผู้ผลิตรายเดียว ซึ่ง แตกต่างจากปกติFlowซึ่งเย็นและเริ่มปล่อยค่าเมื่อต่อกับตัวสะสมเท่านั้น a SharedFlowจะร้อนและเริ่มปล่อยค่าทันทีไปยังตัวสะสมทั้งในปัจจุบันและอนาคตทันทีที่ประกอบ
A SharedFlowอาจมีประโยชน์ในสถานการณ์ที่คุณต้องการแชร์สตรีมข้อมูลระหว่างคอมโพเนนต์ต่างๆ ของแอปพลิเคชัน เช่น เมื่อคุณต้องการแจ้งส่วนต่างๆ ของ UI เกี่ยวกับการเปลี่ยนแปลงข้อมูลบางอย่าง
class MainViewModel : ViewModel() {
private val _items = MutableSharedFlow<List<Item>>()
val items: SharedFlow<List<Item>> = _items
fun startFetchingItems() {
viewModelScope.launch {
while (true) {
val newItems = fetchItemsFromApi()
_items.emit(newItems)
delay(5000)
}
}
}
private suspend fun fetchItemsFromApi(): List<Item> {
// code to fetch items from API
}
}
class MainActivity : AppCompatActivity() {
private lateinit var recyclerView: RecyclerView
private lateinit var adapter: ItemAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recyclerView = findViewById(R.id.recyclerView)
adapter = ItemAdapter(emptyList())
recyclerView.apply {
layoutManager = LinearLayoutManager(this@MainActivity)
setHasFixedSize(true)
this.adapter = [email protected]
}
val viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
lifecycleScope.launchWhenStarted {
viewModel.items.collectLatest { items ->
adapter.updateItems(items)
}
}
viewModel.startFetchingItems()
}
}
collectLatestเป็นฟังก์ชันลำดับที่สูงกว่าใน Kotlin's FlowAPI ที่ให้คุณรวบรวมค่าที่ปล่อยออกมาจาก a Flowและดำเนินการแปลงค่าเฉพาะค่าล่าสุดเท่านั้น ซึ่งคล้ายกับcollectซึ่งใช้เพื่อรวบรวมค่าที่ปล่อยออกมาทั้งหมด แต่collectLatestประมวลผลเฉพาะค่าล่าสุดที่ปล่อยออกมา และละเว้นค่าก่อนหน้าใดๆ ที่ยังไม่ได้ประมวลผล
ความแตกต่างระหว่างโฟลว์ของรัฐและโฟลว์ที่ใช้ร่วมกัน
ต่อไปนี้เป็นข้อแตกต่างที่สำคัญบางประการระหว่างSharedFlowและStateFlowใน Kotlin:
- Mutable vs. Immutable:
StateFlowเป็นตัวเก็บข้อมูลที่ไม่เปลี่ยนรูปซึ่งแสดงถึงค่าเดียวที่สามารถสังเกตได้ ในขณะที่SharedFlowเป็นตัวเก็บข้อมูลที่ไม่เปลี่ยนรูปซึ่งสามารถปล่อยค่าได้หลายค่า - การจัดการข้อผิดพลาด:
StateFlowไม่มีการจัดการข้อผิดพลาดในตัว ในขณะที่SharedFlowรองรับtryEmitฟังก์ชันที่อนุญาตให้ปล่อยค่าอย่างปลอดภัยและเผยแพร่ข้อผิดพลาดไปยังตัวรวบรวมดาวน์สตรีม - การจัดการแรงดันย้อนกลับ:
StateFlowใช้กลยุทธ์แรงดันย้อนกลับที่เรียกว่า "conflation" ซึ่งจะลดค่ากลางโดยอัตโนมัติที่ปล่อยออกมาอย่างรวดเร็วเกินกว่าที่ตัวรวบรวมจะตามทันSharedFlowช่วยให้สามารถควบคุมการจัดการแรงดันย้อนกลับได้อย่างละเอียดยิ่งขึ้นผ่าน พารามิเตอร์bufferและonBufferOverflowพารามิเตอร์ ต่างๆ - พฤติกรรมการแพร่ภาพ:
SharedFlowออกแบบมาเพื่อกระจายค่าไปยังตัวรวบรวมหลายตัว ในขณะที่StateFlowได้รับการออกแบบมาสำหรับการสังเกตค่าเดียว - กรณีการใช้งาน:
StateFlowมักใช้เพื่อแสดงแหล่งที่มาของความจริงแหล่งเดียวในแอปพลิเคชัน เช่น สถานะปัจจุบันของส่วนประกอบ UI หรือข้อมูลในฐานข้อมูลSharedFlowมักจะใช้สำหรับสถานการณ์ที่หลายส่วนของแอปพลิเคชันจำเป็นต้องสังเกตแหล่งข้อมูลเดียวกัน เช่น ในแอพส่งข้อความที่ผู้ใช้หลายคนจำเป็นต้องสังเกตห้องสนทนาเดียวกัน
บทสรุป
โดยสรุป Kotlin's SharedFlowและStateFlowมอบเครื่องมืออันทรงพลังสำหรับนักพัฒนาสำหรับการนำรูปแบบการเขียนโปรแกรมเชิงโต้ตอบไปใช้ในแอปพลิเคชัน Android
StateFlowแสดงถึงค่าเดียวที่ไม่เปลี่ยนรูปและเหมาะอย่างยิ่งสำหรับการแสดงแหล่งที่มาของความจริงแหล่งเดียวในแอปของคุณ
SharedFlowไม่แน่นอนและสามารถปล่อยค่าได้หลายค่า ทำให้เหมาะสำหรับการกระจายค่าไปยังตัวรวบรวมหลายตัว
แต่ละคนมีจุดแข็งและจุดอ่อนของตัวเอง และการเลือกใช้อย่างใดอย่างหนึ่งขึ้นอยู่กับข้อกำหนดเฉพาะของแอปของคุณ
หวังว่าบทความนี้จะเป็นประโยชน์กับคุณ
หากคุณมีข้อเสนอแนะหรือข้อสงสัยใด ๆ โปรดเขียนกลับมาที่[email protected] การตบมือของคุณมีค่ามากที่ช่วยให้ผู้อื่นค้นพบบทความนี้
เพิ่มระดับการเข้ารหัส
ขอบคุณที่เป็นส่วนหนึ่งของชุมชนของเรา! ก่อนที่คุณจะไป:
- ปรบมือให้กับเรื่องราวและติดตามผู้เขียน
- ดูเนื้อหาเพิ่มเติมในสิ่งพิมพ์ Level Up Coding
- หลักสูตรสัมภาษณ์การเข้ารหัสฟรี ⇒ ดูหลักสูตร
- ติดตามเรา: Twitter | LinkedIn | จดหมายข่าว





































![รายการที่เชื่อมโยงคืออะไร? [ส่วนที่ 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)