[Workshop] การนำ Asynchronous Flow มาใช้ในโปรเจก Android แบบเบื้องต้น

Theerapong.Kha
te<h @TDG
Published in
3 min readMay 29, 2020

จากบทความที่แล้วที่สอนการใช้งาน Flow ไปแบบเบื้องต้น ในบทความนี้จะลองนำ Asynchronous Flow มาใช้ในโปรเจกจริง ๆ ในแอปกันครับ

ที่มา What is Flow in Kotlin and how to use it in Android Project? : https://blog.mindorks.com/what-is-flow-in-kotlin-and-how-to-use-it-in-android-project

หากใครยังไม่ได้อ่านบทความสอนการใช้งาน Flow เบื้องต้น สามารถเข้าไปดูเพิ่มเติมได้จากบทความนี้เลย

เริ่มต้นสร้างโปรเจก

โปรเจกนี้จะเป็นการประยุกต์ใช้ความรู้เบื้องต้นของ Coroutines, Flow, Retrofit, MVVM, Glide นำมาประกอบกันเป็นแอปขึ้น

เพื่อความรวดเร็วสามารถ clone โปรเจกที่มีโครงสร้างโค้ดเบื้องต้นไว้แล้วจาก repository นี้ได้เลย โค้ดนี้ได้โค้ด guide มาแล้วบางส่วน จากนั้นเราต้องทำการแก้ไขเพิ่มเติม และเพิ่มโค้ดเข้าไปให้สมบูรณ์ใช้งานได้ต่อไปครับ

สิ่งที่เราต้องมีก่อน คือ API ในการดึงข้อมูลมาแสดงผล หน้าตา JSON ของ API ที่เราจะใช้เพื่อนำมาสร้าง model ของข้อมูล ดังนี้

ตัวอย่างหน้าตาของ API ที่จะนำมาใช้ในแอป

โครงสร้างเริ่มต้นของโปรเจก

แบ่ง package ตามโครงสร้าง MVVM ออกเป็น model, view, viewmodel

โครงสร้างของโปรเจก

จากนั้นไปดูโค้ดเริ่มต้นทีละไฟล์ เริ่มต้นที่ package model มีไฟล์ NewsArticle ทำหน้าที่เป็น Model ของข้อมูลที่รับค่ามาจาก JSON ของ API

ตัวอย่างไฟล์ NewsArticle Model

โค้ดส่วนของ package view ประกอบไปด้วย MainActivity, NewsListAdapter, Util จะเป็น class ในส่วนที่เกี่ยวข้องกับการแสดงผล

  • MainActivity ทำการ setup recyclerView, adapter, view model ไว้ให้เรียบร้อย จากนั้นมาดูที่ function observeViewModel() ไว้รอรับข้อมูลที่ observe มาจาก view model เมื่อมีข้อมูลส่งมาก็ทำการอัพเดตให้ adapter ได้รู้
  • NewsListAdapter เป็น recycle view adapter ทำหน้าที่แสดงผลข้อมูลในแต่ละ item ที่ function onAddNewsItem() รับค่าเป็น NewsArticle model จากนั้นเพิ่มเข้าไปใน list โดยเพิ่มไปในตำแหน่งที่ 0 เพื่อให้แสดงผลในตำแหน่งแรก
  • Util เป็น ImageView extension ที่ช่วยในการโหลดรูปภาพโดยใช้ Glide เป็นตัวจัดการ
ตัวอย่างไฟล์ใน package view

ต่อมาในส่วนของ package viewmodel ที่ class ListViewModel มีตัวแปร newsArticles และมีค่าเป็น mutableLiveData<String> ต่อไปเราจะต้องมาแก้ไขค่านี้ให้ถูกต้อง โดยแปลงเป็น liveData ตามแบบ MVVM pattern

ตัวอย่างไฟล์ ListViewModel

หลังจากรีวิวโค้ดเบื้องต้นเสร็จแล้ว ต่อไปเป็นการลงมือเขียนโค้ดเพิ่มเติมเข้าไปเพื่อทำให้โค้ดสมบูรณ์สามารถทำงานได้จริงกัน

Step 1 ทำการ setup Retrofit

เพิ่ม Gradle dependencies

ตัวอย่างไฟล์ build.gradle

แก้ไขไฟล์ NewsArticle

เราจะต้อง map ตัวแปรใน model ให้ตรงกับค่า JSON ที่ได้รับจาก API ทำการแก้ไขไฟล์ model ของเราเพิ่มเติม โดยในนี้มีค่า urlToImage ที่ยังไม่ตรงกัน สามารถใช้ SerializedName เข้ามาช่วย map ชื่อตัวแปร กับค่าใน API ได้ โดยทำการเติม @SerializedName(“imageUrl”) ให้กับ urlToImage

ตัวอย่างไฟล์ NewsArticle

สร้างไฟล์ NewsService

ต่อไปทำการสร้าง service ของเรา ด้วยการสร้างไฟล์ NewsSercviceใน package model ด้วยความสามารถของ Coroutine และ Retrofit เราสามารถเติม suspend นำหน้า function และให้ชนิดข้อมูลที่จะ return ค่าเป็น model ของข้อมูลตามรูปแบบของ JSON ได้เลย

สามารถอ่านเพิ่มเติมได้ที่นี่

ตัวอย่างไฟล์ NewsService

สร้างไฟล์ NewsRepository
ทำการสร้างไฟล์ใน package model โค้ดในส่วน NewsRepository จะมีระบุ base url ของ API และมี function ที่จะเป็นตัวกลางที่ไปเอาข้อมูลจาก API ส่งไปให้ View Model

  • ทำการสร้างตัวแปร newsService ซึ่งทำหน้าที่ติดต่อกับ API ด้วย Retrofit ทำการระบุ base url ของ API ใส่ Gson converter ให้เรียบร้อย และ create interface ของ NewsService
  • ที่ function getNewsArticles() จะเป็นโค้ดที่เราประยุกต์การใช้ Flow ในแอปของเรา โดยเมื่อเราสั่ง newsService.getNews() ก็จะได้รับค่าจาก API มาเก็บไว้ใน newSource จากนั้นทำการลูปทีละค่า และ delay ทุก 2 วินาที จึงส่งข้อมูล emit ออกไปจนครบ
ตัวอย่างไฟล์ NewsRepository

Step 2 การใช้งาน Flow

แก้ไขไฟล์ ListViewViewModel ใน package viewmodel

ขั้นตอนสุดท้ายของ workshop นี้ คือ การที่ view model ไปนำข้อมูลจาก repository มา จากนั้นทำการแปลงให้เป็น liveData เพื่อส่งไปให้ใครก็ตามที่ observe อยู่ นำค่านี้ไปใช้งาน หรืออัพเดตใน UI และด้วยความสามารถของ androidx.lifecycle:lifecycle-livedata-ktx ทำให้เราสามารถแปลงข้อมูลจาก Flow มาเป็น LiveData ได้เลย ด้วยคำสั่ง asLiveData()

ตัวอย่างไฟล์ ListViewModel

หมายเหตุ : เราสามารถนำข้อมูลจาก Flow มาใช้งานแบบปกติด้วยการใช้ collect หรือ onEach เพียงแต่บทความนี้จะพาใช้วิธีแปลงเป็น LiveData จาก Flow ด้วยการใช้งาน asLiveData ซึ่งอีกวิธีการสามารถทำได้ ดังนี้

การใช้งาน collect, onEach เพื่อรับค่าที่ส่งมาจาก Flow

Step 3 รันทดสอบผล

ก็เป็นอันเสร็จพิธี ในการแก้ไขเพิ่มเติมประกอบโค้ดให้สมบูรณ์ จากนั้นลองทดสอบรัน เพื่อดูการทำงานได้เลย เมื่อรันเสร็จแล้ว จะเห็นว่าแอปจะมีนำ Item มาแสดงผลเพิ่มเติมในทุกๆ 2 วินาที จนกว่าของที่ถูก emit มาจาก repository จนครบ

ตัวอย่างแอปที่เราได้จาก workshop นี้

ข้อสรุป

นี่ก็เป็นตัวอย่างการลองนำความรู้มาประยุกต์เพื่อนำมาสร้างเป็นแอปจริง ๆ เป็นตัวอย่างการใช้งาน Flow ในแอปของเรา รวมถึงมีการติดต่อเพื่อดึงข้อมูลจากฝั่ง backend API ในการเรียกใช้งานผ่าน Retrofit เพื่อนำมาแสดงผล การจัดการเรื่องรูปภาพด้วย Glide และเขียนโค้ดในรูปแบบของ MVVM ซึ่งการได้ลองทำเป็นโปรเจกจริง ๆ จะช่วยให้เห็นภาพมากขึ้น และเป็นไอเดียนำไปต่อยอดสร้างแอปที่ใหญ่ขึ้น มีฟีเจอร์หลากหลายยิ่งขึ้นต่อไป และหวังว่าบทความนี้จะเป็นประโยชน์ต่อผู้อ่านที่สนใจไม่มากก็น้อย

ข้อมูลอ้างอิง

Source Code

--

--