มาทำความรู้จัก Product Flavors กันเถอะ !!

Supitsara Prathan
japaipaipai
Published in
3 min readDec 31, 2016

เมื่อผู้เขียนและทีมได้รับโจทย์ให้ปรับปรุงโค้ดจากเดิมที่โครงสร้างโปรเจคมีลักษณะคล้ายๆ แบบนี้

จากไดอะแกรมด้านบนจะเห็นได้ว่าโปรเจคนั้นเริ่มต้นมาจาก branch 1 เป็น branch แรก และได้มีการพัฒนาต่อมาเรื่อยๆ ก็มีความต้องการที่จะสร้างอีกแอพนึงซึ่งมีการทำงานหลักๆ เหมือนกับแอพตัวแรก (แต่ Theme และ layout บางหน้าไม่เหมือนกันนะ) จึงแยก branch ออกมาจาก branch 1 แล้วแก้ไขพวก Theme และหน้าตาให้เป็นของแอพตัวที่ 2 แล้วก็พัฒนาควบคู่กันมากับแอพตัวแรก (ซึ่งก็คือ branch 1) โดยยึด branch 1 เป็นหลัก คือ เมื่อมีการพัฒนาหรือเพิ่ม feature ให้กับ branch 1 ก็จะต้องทำอย่างนั้นกับ branch 2 ด้วย ถ้ามันมีแค่ 2 branchs ก็น่าจะไม่เป็นไรใช่มั้ยล่ะครับ แล้วถ้ามันมีเพิ่มขึ้นมาเรื่อยๆล่ะ จาก 2 เป็น 5 จาก 5 เป็น 10 ก็คงจะดูแลลำบากใช่มั้ยล่ะครับ นั่นคือปัญหาที่ผู้เขียนและทีมกำลังเจอครับ หลังจากศึกษาดูว่ามีวิธีไหนบ้างที่สามารถแก้ปัญหาเหล่านี้ได้ จึงได้พบกับเจ้านี่ Product Flavors สำหรับมือเก๋าหลายๆท่านก็คงจะคุ้นเคยกันดีอยู่แล้ว แต่สำหรับมือใหม่ที่ยังไม่รู้จัก มาทำความรู้จักกับเจ้านี่ไว้ จะทำให้ชีวิตคุณสบายขึ้นเป็นกองเลยครับ

Product Flavors

ถาม : มันคืออะไร ?
ตอบ : มันคือคำสั่งที่ทำให้เราสามารถแยก build app ออกมาเป็นหลาย version ได้ เช่นเรามีแอพ 2 versions คือ free กับ premium เป็นต้น

ถาม : มันใช้ยังไง ?
ตอบ : เพิ่มคำสั่งลงไปในไฟล์ build.gradle ของ app แบบนี้

ดังตัวอย่างเป็นการกำหนดว่าในโปรเจคของเรานั้นสามารถ build ออกมาได้ 2 แบบ คือ strawberry และ blueberry ซึ่งในการจะ build ออกมาเป็นแบบไหนนั้นเราสามารถเลือกได้จากแถบ Build Variants ทางซ้ายมือ แบบนี้

แต่เดี๋ยวก่อนนนนนนนน !!

ก่อนที่เราจะลอง build app เราลืมอะไรไปรึเปล่า ? …
ใช่ครับ !! เรายังไม่ได้สร้าง directory ของ strawberry และ blueberry เลย
เพราะฉะนั้น เราต้องไปสร้าง directory ของทั้งสอง flavors ก่อน แบบนี้

โปรดสังเกตที่โฟลเดอร์ res ของทั้ง 3 directory ดูครับ สัญลักษณ์จะแตกต่างกัน โดยของ blueberry จะเป็นสีเทา แต่ของ main และ strawberry จะเป็นสีส้ม ซึ่งนั่นหมายความว่าขณะนี้เราได้เลือก Build Variants เป็น strawberry อยู่นั่นเอง แต่ที่ main เป็นสีส้มด้วยนั่นก็เพราะว่า main เป็น core ของโปรเจคที่ไม่ว่าจะ build เป็น flavor ไหน ก็จะต้องมี main อยู่ด้วยเสมอ

คราวนี้ก็ลองกด Run ดูครับ จะได้ผลลัพธ์แบบนี้…

ซึ่งผลลัพธ์ที่ได้ก็ขึ้นอยู่กับว่าเราเลือก Build Variants เป็น Flavor ไหน แสดงตามชื่อของ application ตามที่เราใส่ไว้ในไฟล์ strings.xml ในแต่ละ Flavor ซึ่งของผู้เขียนกำหนดชื่อของ application ของ strawberryFlavor ไว้เป็น StrawBerry ดังนี้

ต่อไปเรามาลองปรับแต่งหน้า main ของแต่ละ Flavor กัน โดยผู้เขียนต้องการให้สีของ TitleBar เป็นสี Primary ของแต่ละ Flavor ผู้เขียนก็แค่ไปแก้ที่ไฟล์ style.xml ของตัว main ที่เดียว

ส่วนค่าของ colorPrimary ของแต่ละ Flavor นั้นก็ต้องไปเซ็ตที่ไฟล์ colors.xml ของแต่ละ Flavor นะครับ ซึ่งจะใช้สีอะไรก็ตามชอบเลยครับ ผลลัพธ์ก็จะออกมาประมาณนี้

จากตัวอย่างจะเห็นได้ว่าหน้าตาของ activity นั้นมี layout ที่เหมือนกัน แตกต่างกันเฉพาะสีและตัวอักษรเท่านั้น ก็เพราะว่าทั้งสอง Flavors นั้นต่างก็ใช้ไฟล์ layout ที่ชื่อ activity_main.xml จาก directory main นั่นเอง

แล้วถ้าในกรณีที่ต้องการให้ layout ที่ชื่อ activity_main.xml ของแต่ละ Flavors มีหน้าตาที่แตกต่างกันล่ะ ?

ถ้าเราแค่ต้องการให้ตำแหน่งของ component ใน layout แตกต่างกันเท่านั้น เราสามารถแยกไฟล์ activity_main.xml ออกมาเขียนใน layout ของแต่ละ Flavors ได้ หรือจะแยกออกมาเฉพาะ Flavor อันใดอันหนึ่งก็ได้ เพราะ layout จาก Flavor สามารถ Override layout ที่อยู่ใน main ได้ แต่ถ้า layout ยังผูกอยู่กับไฟล์ MainActivity.java ใน main ต้องระวังการ custom layout ที่อยู่ใน Flavor เพราะหากสร้าง component ที่ MainActivity.java มีการเรียกใช้ไม่ครบก็จะไม่สามารถรันแอพได้นั่นเอง

แล้วทีนี้จะทำยังไงล่ะถ้าหากมีบาง screen ที่หน้าตาแตกต่างกันแล้วยังมีการทำงานที่แตกต่างกันด้วย ?

ถ้าต้องการให้มีหน้าตาที่แตกต่างกันก็แค่แยกไฟล์ layout ออกมาเป็นของแต่ละ Flavors ใช่มั้ยล่ะ activity ก็เช่นกัน ถ้าอยากให้มีหน้าตาและการทำงานที่แตกต่างกันก็แค่แยกออกมาสร้าง activity ของแต่ละ Flavors เช่น จากหน้า main ด้านบนหากกดปุ่มตรงกลางแล้วจะไป activity ต่อไป (ขอตั้งชื่อว่า LoginActivity) แต่อยากให้เจ้า LoginActivity เนี่ยมีหน้าตาและการทำงานที่ต่างกัน ก็สร้างเจ้า LoginActivity ในทั้งสอง Flavors ไปเลยแบบนี้
*** แต่มีข้อควรระวัง คือ เราไม่สามารถมี class ที่ชื่อเหมือนกันอยู่ในทั้ง main และ Flavors ได้ เหตุผลเพราะว่ามันจะทำให้เกิด error: duplicate class เพราะฉะนั้นถ้าเราสร้าง activity ใดใดไว้ที่ Flavors เราก็ไม่จำเป็นต้องสร้างไว้ที่ main

เมื่อสร้าง LoginActivity ในแต่ละ Flavors แล้วก็ลอง custom หน้าตาและการทำงานตามจินตนาการของแต่ละท่านได้เลยครับ ของผู้เขียนขอทำแบบง่ายๆนะครับ แบบนี้

จากตัวอย่าง หลายคนอาจจะคิดว่ามันก็แตกต่างกันไม่มากนี่ แต่จริงๆแล้วมันมาจาก layout คนละไฟล์กันครับ (สามารถสร้างให้แตกต่างกันคนละทิศละทางเลยก็ได้ แต่เพราะมันเป็น LoginActivity มันเลยไม่ควรจะฉีกออกจากความเป็นจริงครับ) และการทำงานของหน้านี้ก็สามารถกำหนดได้ที่ไฟล์ LoginActivity.java ของใครของมันตามแต่ละ Flavors เลยครับ

สรุป

Product Flavors เหมาะสำหรับโปรเจคที่ต้องการ build ออกมาเป็นหลายๆ แอพที่มีการทำงานหลักๆ เหมือนกัน แต่มีบางหน้าที่ไม่เหมือนกัน **ย้ำว่าแค่บางหน้านะครับ ไม่จำเป็นว่าจะต้องเป็นแอพเวอร์ชัน Free กับ Paid เท่านั้น แต่สามารถนำมาประยุกต์ใช้กับบางโปรเจคที่มีความต้องการลักษณะนี้ได้ (อย่างเช่นที่ผู้เขียนเจอ) ซึ่งการจะใช้ Product Flavors ให้มีประสิทธิภาพนั้น เราควรออกแบบโครงสร้างของโปรเจคที่เราจะสร้างว่ามีอะไรบ้างที่ควรอยู่ในส่วน main ซึ่งทุก Flavors ใช้ร่วมกัน และอะไรบ้างที่เป็นการ custom ของแต่ละ Flavors เมื่อเราชัดเจนในส่วนนี้การเขียนโค้ดต่อไปก็จะเป็นไปด้วยความมีระเบียบ และง่ายต่อการบำรุงรักษา

--

--