26 August 2016

เรื่องเล่าจาก Instant Run สุดเทพบน Android Studio

Updated on


      สำหรับ Android Dev แล้ว เมื่อได้ยินคำว่า Instant Run เมื่อไหร่ ส่วนใหญ่ก็จะคงรู้จักกับชื่อนี้กันเป็นอย่างดี เพราะมันคือหนึ่งในฟีเจอร์ของ Android Studio ที่ทางทีมพัฒนาได้เพิ่มเข้าในตั้งแต่เวอร์ชัน 2.0 เป็นต้นไป ซึ่งบอกเลยว่าฟีเจอร์นี้จะเข้ามาเปลี่ยนชีวิตของ Android Dev อย่างมากโขเลยล่ะ!

       เพราะสิ่งแรกที่จะมาเปลี่ยนชีวิตของ Android Dev ก็คือ "เข้าไปปิดแม่มทิ้งซะ!!"

กำเนิด Instant Run

        ถึงแม้ว่า Android Dev ส่วนใหญ่จะรู้จักกัน แต่ก็ใช่ว่าทุกๆคนนั้นจะเข้าใจเกี่ยวกับ Instant Run อย่างลึกซึ้ง ดังนั้นเจ้าของบล็อกก็คงต้องขอเกริ่นอธิบายเกี่ยวกับ Instant Run ให้ผู้ที่หลงเข้ามาอ่านรู้จักกันก่อนเนอะ ส่วนผู้ที่หลงเข้าอ่านคนไหนที่รู้จักอยู่แล้วก็สามารถข้ามไปได้เลยจ้า หรือจะอ่านเพื่อเก็บรายละเอียดปลีกย่อยก็ได้เช่นกัน

        Android Studio เป็น IDE ที่ค่อนข้างฉลาดมาก+เทพครับ เมื่อเทียบกับ IDE หลายๆตัวที่เจ้าของบล็อกเคยใช้มา ซึ่งเบื้องหลังความเทพของมันก็คือ IntelliJ IDEA นี่แหละ (ต้องกราบขอบพระคุณงามๆ ที่เปลี่ยนจาก Eclipse มาเป็น IntelliJ IDEA)

        แต่ถึงแม้จะมีความฉลาดและเทพสูงมากก็ตาม แต่อะไรที่ฉลาดมากก็หมายความว่ามันต้องคิดให้เราล่วงหน้าไว้เยอะ ช่วยคำนวณแทนเราไว้เยอะ เพราะงั้นเป็นเรื่องปกติที่ Android Studio จะกลายเป็นหนึ่งใน IDE ที่โคตรกินสเปคคอมพิวเตอร์ ซึ่งส่วนใหญ่ก็มาจาก Gradle เนี่ยแหละ

        เจ้าของบล็อกเชื่อว่าความน่ารำคาญระหว่างการเขียนโค้ดของ Android Dev ส่วนใหญ่จะอยู่ที่ตอน Gradle ทำงาน ดังนั้นใครที่รู้สึกว่า Gradle ทำงานช้ามากบนเครื่องตัวเอง โปรดอย่าแปลกใจครับ อย่างน้อยก็ไม่ใช่แค่ผู้ที่หลงเข้ามาอ่านคนเดียวหรอกน่ะ เพราะ Gradle จะทำขั้นตอนทั้งหมดใหม่ทุกครั้งที่แก้ไขโค้ดแล้วอยากจะเห็นการทำงานว่าเป็นไปตามที่ต้องการหรือป่าว


        ซึ่งทาง Android Studio ก็ไม่ได้นิ่งนอนใจครับ (เจ้าของบล็อกเชื่อว่าคนในทีมพัฒนา Android Studio ก็คงเบื่อปัญหานี้เหมือนกันแหละ) จึงได้พัฒนาสิ่งที่เรียกว่า Instant Run เพิ่มเข้ามา และเริ่มให้ใช้งานตั้งแต่ Android Studio 2.0 เป็นต้นมา


        ปกติแล้วเวลา Dev เขียนโค้ดเสร็จก็มักจะกดปุ่ม Run เพื่อรันแอปฯบน Emulator หรือเครื่องจริงๆใช่มั้ยล่ะครับ ซึ่ง Android Studio ก็จะทำการ Compile โค้ดให้กลายเป็น APK โดยมี Gradle เป็นหัวใจสำคัญในขั้นตอนนั้น และนั่นแหละครับที่ Gradle ได้แสดงความสามารถที่แท้จริงออกมาให้เห็นเป็นประจักษ์

        "Build นานชิบหาย"

        "ไปชงกาแฟดีกว่า"

        "จับโปเกมอนได้หลายตัวเลย"

        ก็นั่นล่ะฮะ ยิ่งโปรเจคใหญ่มากเท่าไร ก็ยิ่ง Build นานเท่านั้น (เจ้าของบล็อกเคยเจอโปรเจคใหญ่ขนาด Build นาน 6 นาที)

        เนื่องจากปัญหาคือกด Run หนึ่งครั้ง มันก็จะไป Build โปรเจคให้กลายเป็น APK ทุกครั้ง

        แต่...จะดีกว่ามั้ยถ้า Dev สามารถอัปเดตโค้ดได้โดยที่ไม่ต้อง Build ใหม่

        นั่นล่ะครับคือจุดเริ่มต้นของ Instant Run บน Android Studio

Instant Run คืออะไร?

        เป็นฟีเจอร์ของ Android Studio ที่จะช่วยให้ Dev แก้ไขโค้ดแล้วอัปเดตบนเครื่องโดยไม่ต้อง Compile ใหม่ นั่นหมายความว่ามันจะกระโดดข้ามผ่านขั้นตอนหลายๆอย่างของ Gradle ที่ทำให้เสียเวลา Compile นานนั่นเอง

        หลักการของ Instant Run คือ เมื่อ Dev เปิดใช้งาน Instant Run บน Android Studio ในครั้งแรกที่ Gradle ทำการ Build ก็จะใช้เวลานานเหมือนเดิมแหละ แต่เจ้าตัว Android Studio จะแอบปรับเปลี่ยนโค้ดเล็กน้อย เพื่อให้ตัวแอปฯเชื่อมต่อกับ Android Studio อยู่ตลอดเวลาที่มันทำงาน (นั่นหมายความว่า Instant Run จะหยุดทำงานถ้า Emulator หรืออุปกรณ์แอนดรอยด์ถูกถอดออก) จากนั้นเมื่อมีการแก้ไขโค้ดก็จะส่งชุดโค้ดที่มีการเปลี่ยนแปลงไปแทนที่ของเก่าบนอุปกรณ์แอนดรอยด์ทันที เย้!


        จะเห็นว่า Instant Run ทำให้ชีวิตของ Dev ทันใจมากขึ้นในระดับวินาทีเลยล่ะ!!

การทำงานแบบเบื้องลึก

        เบื้องหลังความสามารถนี้คือ Android Studio แอบไปปรับเปลี่ยนโค้ดในแอปฯให้สามารถทำงานเป็น App Server ได้ และให้เชื่อมต่อกับ Android Studio อยู่ตลอดเวลา เพื่อที่จะได้อัปเดตโค้ดเฉพาะบางส่วนได้โดยไม่ต้องไป Compile ใหม่

        อาจจะฟังดูเหมือนง่าย แต่ก็มีเรื่องจุกจิกมากมายที่เกิดขึ้นอยู่เบื้องหลังนี้ ก่อนอื่นมาดูรูปนี้กันก่อน


        ภาพข้างบนนี้เป็นรูปขั้นตอนการทำงานโดยปกติของ Android Studio เมื่อ Compile โค้ดให้กลายเป็น APK

        • Manifest หรือ ที่รู้จักกันในชื่อของ Android Manifest จะถูกรวม (Merge) เข้าด้วยกัน (เพราะไลบรารีทุกตัวมี Manifest ของตัวเอง ดังนั้นในหนึ่งโปรเจคก็จะมี Manifest หลายไฟล์) เมื่อรวมเสร็จแล้วก็จะส่งต่อไปให้ AAPT

        • ซึ่งเจ้า AAPT หรือชื่อเต็มๆคือ Android Asset Packaging Tool ที่ทำหน้าที่จัดการกับ Resource ทั้งหมดของแอนดรอยด์ ก็จะไปรวมไฟล์ Resource ทั้งหมด (พวก XML ในโปรเจคก็คือ Resource นั่นเอง รวมไปถึง Android Manifest ที่ Merge เสร็จแล้วด้วย) เพื่อเอาไปเก็บไว้ใน APK

        • ฝั่ง Java ก็จะถูก javac ทำการ Compile โค้ด Java ให้กลายเป็น .class จากนั้นก็จะถูกทำให้กลายเป็นไฟล์ .dex อีกทีแล้วเก็บไว้ใน APK

        แต่พอมีการใช้ Instant Run เพิ่มเข้ามา APK ที่ได้จากการ Build โดยมี Instant Run อยู่ด้วย ก็จะมีการเพิ่มโค้ดบางอย่างเพื่อให้สามารถอัปเดตโค้ดแบบทันทีได้


        เมื่อดูจากภาพข้างบน (และไม่รู้สึกว่ามันงง) ก็จะเห็นว่าการทำงานของ Instant Run จะเข้าไปแทรกขั้นตอนเดิมๆของการ Build APK เพื่อตรงจุดที่แทรกนี่แหละจะไปปรับเปลี่ยนเล็กน้อยเพื่อให้ได้ไฟล์ APK ที่สามารถอัปเดตโค้ดได้โดยไม่ต้อง Compile ใหม่

        Instant Run จะถูกแทรกเข้าไปใน Android Manifest (เพราะมันต้องแทรกโค้ดใน Android Manifest เพื่อให้ทำงานเป็น App Server ได้)



        และ Instant Run จะแทรกเข้าไปใน .class ที่ถูก Compile ด้วย javac แล้วส่งให้ dex ต่อ ในขณะเดียวกันก็จะมีการแทรกไฟล์ Application และ App Server ของ Instant Run เพิ่มเข้าไปอีกด้วย



        นั่นหมายความว่า Android Manifest กับ .dex ที่อยู่ใน APK มีการติดตั้งโค้ดของ Instant Run แล้วนั่นเอง

        และตัวโค้ดในโปรเจคทั้งหมดจะถูกแบ่งออกเป็นหลายๆชุดด้วยกัน (เห็นเค้าว่า 11-12 ชุด) และแต่ละชุดจะมี .dex เป็นของตัวเอง ซึ่งแต่ละชุดจะแยกจากกัน เป็นคนละ Package เพื่อที่ว่าเวลามีการแก้ไขโค้ดใดๆก็ตามก็จะสามารถอัปเดตเฉพาะบางชุดได้ ซึ่ง Gradle ก็จะคอยเช็คในส่วนนี้ให้ว่าโค้ดส่วนไหนมีการเปลี่ยนแปลง

การใช้งาน Instant Run

        ใน Android Studio เวอร์ชันหลังๆส่วนใหญ่จะเปิด Instant Run ให้ตั้งแต่แรกอยู่แล้วนะ แต่ก็จะบังคับว่าให้อัปเดต Gradle Plugin ตามด้วย แต่ถ้าของผู้ที่หลงเข้ามาอ่านคนใดไม่ได้เปิดใช้งานอยู่ก็ลองเข้าไปดูวิธีเปิดใช้งานได้ที Android Studio 2.0 :: ทำความรู้จักกับ Instant Run เร็วฟ้าผ่ากัน

        ใช้งานได้หรือไม่ให้สังเกตที่ปุ่ม Run ครับ เพราะมันจะมีสัญลักษณ์สายฟ้าสีเหลืองๆอยู่ด้วย ซึ่งในการ Build ครั้งแรก (เรียกกันว่า Full Buid) จะยังไม่มีสัญลักษณ์นี้ แต่เมื่อ Build เสร็จและแอปฯก็ถูกติดตั้งลงในอุปกรณ์แอนดรอยด์แล้ว ก็จะเห็นสัญลักษณ์นี้เพิ่มเข้ามาแทนครับ


        แต่ในกรณีทีเปิด Instant Run ให้กับโปรเจคแล้วไม่มีสัญลักษณ์ดังกล่าว ให้ลองเช็คว่า Gradle Plugin อัปเดตเป็นเวอร์ชันล่าสุดแล้วหรือยัง

แต่สุดท้ายก็ปิด Instant Run อยู่ดี...

        ถึงแม้ว่า Instant Run จะทำให้สามารถอัปเดตโค้ดได้ทันทีโดยไม่ต้อง Compile ใหม่ แต่ Dev ส่วนใหญ่ก็เจอปัญหาเวลาแก้ไขโค้ดแล้วโค้ดไม่ส่งผลบ้าง หรืออัปเดต Resource แล้วไม่เปลี่ยนแปลงบ้าง ทั้งนี้ก็เพราะว่าตัว Instant Run ยังไม่ได้สมบูรณ์โดยแท้ แต่จะมีการอัปเดตปรับปรุงอยู่ตลอดเวลาใน Android Studio เวอร์ชันใหม่ๆ

        แต่ทว่าก็ยังส่วนหนึ่งที่เจ้าของบล็อกพบก็คือ Instant Run ทำงานถูกต้องแล้ว แต่ Dev ไม่ได้เข้าใจการทำงานของ Instant Run จึงทำให้เข้าใจผิดว่า Instant Run ทำงานไม่ถูกต้อง

        ถ้ายังอยากปิด Instant Run จริงๆ ก็สามารถเข้าไปปิดใน Preference ของ Android Studio ได้เลย


รู้จักกับ 3 รูปแบบการทำงานของ Instant Run

        อาจจะฟังดูเหมือนว่า Instant Run จัดการให้หมดแล้ว แต่จริงๆแล้วผู้ที่หลงเข้ามาอ่านควรทำความเข้าใจกับรูปแบบการทำงานของ Instant Run ก่อน เพราะเวลาที่มันทำงานในแต่ละรูปแบบจะมีผลลัพธ์ที่ต่างกันนั่นเอง ซึ่งมีดังนี้

        • Hot Swap
        • Warm Swap
        • Cold Swap

Hot Swap  รวดเร็วทันใจ

        เป็นการเปลี่ยนโค้ดในฉับพลันเลย ซึ่งเป็นรูปแบบที่ Instant Run ทำงานได้ไวที่สุดแล้ว โดยจะทำงานเมื่อมีการแก้ไขโค้ดที่มีอยู่แล้วใน Method แต่ละตัว (พวกคำสั่งเล็กๆน้อยๆนั่นแหละ) โดย Instant Run จะส่งโค้ดตัวนั้นๆเข้าไปทันที และทำการ Override คำสั่งเก่าๆซะเพื่อให้เรียกมาที่คำสั่งอัปเดตใหม่


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

        ซึ่งการทำงานรูปแบบนี้จะช่วยอำนวยความสะดวกกับ Dev มากๆในเวลาที่แก้ไขโค้ดเล็กๆน้อยๆเท่านั้น เพราะมันใช้เวลาไวมาก​ (ขึ้นอยู่กับว่าแก้ไขโค้ดมากน้อยแค่ไหนด้วย) และส่วนใหญ่ใช้เวลาไม่ค่อยเกิน 10 วินาทีด้วยซ้ำ!!

        เงื่อนไข
        • แก้ไขโค้ดที่เดิมมีอยู่แล้ว โดยไม่ส่งผลกับโค้ดโดยรวมมากนัก

        ผลลัพธ์จากการทำงาน
        • โค้ดเปลี่ยนแปลงทันทีโดยไม่ส่งผลอะไรกับแอปฯที่ทำงานอยู่
        • โค้ดจะมีผลเมื่อเรียกใช้งานคำสั่งนั้นๆในครั้งต่อไป
        • Activity ยังคงทำงานอยู่เหมือนเดิม ไม่มีการถูกทำลายเพื่อสร้างขึ้นมาใหม่

Warm Swap ไม่เร็วมากนัก แต่ก็ยังถือว่าเร็วอยู่ดี

        เมื่อมีการแก้ไขเกี่ยวกับ Resource จะไม่สามารถทำ Hot Swap ได้ เพราะ Resource มันจะต้องมีการ Repack ใหม่แล้วอัปเดตให้กับตัวแอปฯ ดังนั้นเวลาที่มีการแก้ไขหรือลบ หรือเปลี่ยนแปลงอะไรใน Resource ก็จะทำให้เกิด Warm Swap นั่นเอง

        เงื่อนไข
        • แก้ไขหรือลบ Resource ใดๆก็ตาม เช่น แก้ไขข้อความใน String XML หรือลบ Value XML บางตัวออกไป หรือจัดย้ายตำแหน่งของ View ใน Layout XML ใหม่

        ผลลัพธ์จากการทำงาน
        • Resource จะมีการอัปเดตใหม่ โดยที่ไม่ต้องติดตั้งแอปใหม่
        • Activity จะถูก Recreate ใหม่เพื่ออัปเดต Resource

Cold Swap แบบช้าๆ แต่ก็ดีกว่า Full Build

        เป็นรูปแบบการทำงานเฉพาะบน API 21 ขึ้นไปเท่านั้น เวอร์ชันที่ต่ำกว่านั้นจะกลับไปเป็น Full Build ทั้งหมด ซึ่ง Cold Swap จะเกิดขึ้นก็ต่อเมื่อมีการแก้ไขโค้ดที่ส่งผลต่อ Structure ที่ไม่สามารถทำ Hot Swap ได้แล้ว (เพราะโค้ดไม่ได้มีการเปลี่ยนแปลงเฉพาะบางจุดที่สามารถ Override ทับได้) หรือแก้ไข Resource ที่ต้อง Reindex ใหม่ 

        เนื่องจากโค้ดของ Dev จะถูกแบ่งออกเป็นหลายๆชุด ซึ่ง Cold Swap นี่แหละที่จะไป Compile และอัปเดตโค้ดของชุดที่มีการเปลี่ยนแปลงเท่านั้น ทำให้โค้ดที่อยู่คนละชุดไม่ต้องเสียเวลา Compile ใหม่


        เงื่อนไข
        • ทำงานเฉพาะบน API 21 ขึ้นไปเท่านั้น เวอร์ชันที่ต่ำกว่าจะกลายเป็น Full Build แทน
        • มีการเพิ่ม/ลบ/แก้ไขโค้ดที่ส่งผลต่อ Structure ของโปรแกรม
                • Annotation
                • Instance Field
                • Instance Method
                • Static Field
                • Static Method
                • Static Class Initializer
                • Parent Class ของ Class
                • Interface
        • มีการแก้ไขหรือเพิ่ม Resource ตัวใหม่เข้ามาที่ส่งผลให้ AAPT ต้อง Reindex เพื่อสร้าง ID ของ Resource แต่ละตัวใหม่

        ผลลัพธ์จากการทำงาน
        • แอปฯจะถูกปิดลงแล้วเปิดขึ้นมาใหม่
        • ก็ต้องติดตั้ง APK ใหม่อยู่ดี แต่ลดเวลาตอน Build มากกว่า Full Build

แต่การแก้ไข Android Manifest ก็ต้อง Full Build อยู่ดี

        ถึงแม้ว่า Instant Run จะช่วยหลายๆการกระทำให้สะดวกขึ้น แต่เมื่อแก้ไข Android Manifest ก็ยังต้องต้องทำ Full Build ทุกครั้ง เนื่องจาก Android Manifest เป็นไฟล์ที่อุปกรณ์แอนดรอยด์จะเปิดอ่านข้อมูลเฉพาะครั้งแรกตอนที่ติดตั้ง APK เท่านั้น ดังนั้นจึงเลี่ยงไม่ได้ที่จะต้องทำ Full Build เพื่อเข้าขั้นตอนติดตั้ง APK ใหม่

ข้อจำกัดบางอย่าง

        ถึงแม้ว่า Instant Run จะดีงามก็จริง แต่ก็ยังมีบางอย่างที่เป็นข้อจำกัดอยู่เหมือนกัน อย่างเช่น ไม่สามารถใช้ร่วมกับ Jack Compiler  ไม่สามารถใช้กับ Instrumentation Test และไม่สามารถ Deploy บนอุปกรณ์แอนดรอยด์หลายๆเครื่องพร้อมๆกันได้

        และก็ยังมีบั๊กเวลาแก้ไข View แล้วเกิดอาการเพี้ยนๆเป็นบางครั้ง (แก้ไขด้วยการ Run > Clean and Rerun)

สิ่งที่นักพัฒนามักจะเข้าใจผิด

        เจ้าของบล็อกเชื่อว่าผู้ที่หลงเข้ามาอ่านส่วนใหญ่น่าจะเจออะไรคล้ายๆกันเวลาใช้ Instant Run โดยเฉพาะเวลาที่ใช้งานแล้วรู้สึกว่า Instant Run ทำให้แอปฯแสดงผลเพี้ยนๆบ้าง ไม่อัปเดตค่าบ้าง สุดท้ายก็ต้องมานั่ง Clean Project ใหม่ทุกครั้งเพื่อให้มันทำงานได้เหมือนเดิม

        กดต้องมานั่งกด Clean Project บ่อยๆ แล้ว Instant Run มันจะมาช่วยให้เร็วขึ้นได้ยังไงล่ะเนอะ? เพราะงั้นก็ปิด Instant Run แม่มซะเลย

        แต่ทีนี้เจ้าของบล็อกอยากให้มาดูก่อนว่า จริงๆแล้วไอ้ปัญหาที่เจอกันระหว่างใช้งาน Instant Run เกิดมาจากความเข้าใจผิดหรือป่าว หรือโค้ดทำงานไม่ถูกต้องตั้งแต่แรกแล้วหรือป่าวนะ?

        กรณีแรกสุดที่เจอกันได้ค่อนข้างบ่อยคือ Concept ของ Instant Run คือแก้ไขแล้วเปลี่ยนแปลงเห็นผลในไม่กี่วินาที จึงทำให้นักพัฒนาส่วนใหญ่เข้าใจว่าถ้าแก้ไขบางอย่างแล้วจะต้องอัพเดทให้เห็นผลคำสั่งนั้นๆทันทีในทุกครั้ง

        ยกตัวอย่างเช่น เจ้าของบล็อกมีคำสั่งของ Activity แบบง่ายๆอยู่ตัวหนึ่ง

public class VeryAwesomeActivity extends Activity {
    private static final String TAG = VeryAwesomeActivity.class.getName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_very_awesome);

        Log.e(TAG, "Hello World");
    }
}

        ถ้าดูจากโค้ดคร่าวๆก็จะเห็นว่า เป็น Activity ที่จะแสดงคำว่า Hello World ใน Logcat เมื่อตอนที่ Activity ตัวนี้ถูกสร้างขึ้น

        แล้วเกิดเจ้าของบล็อกเปลี่ยนใจอยากใช้ Toast แทนล่ะ

public class VeryAwesomeActivity extends Activity {
    private static final String TAG = VeryAwesomeActivity.class.getName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_very_awesome);

        Toast.makeText(this, "Hello World", Toast.LENGTH_SHORT).show();
    }
}

        พอกด Run ด้วย Instant Run ปุ๊ป สิ่งที่เกิดขึ้นคือข้อความควรเปลี่ยนจากใน Logcat มาแสดงเป็น Toast ใช่มั้ยล่ะครับ

        สิ่งที่เกิดขึ้นคือ ไม่มีอะไรเกิดขึ้นเลย Toast ไม่มีการแสดงข้อมูลเลย ทั้งๆที่มีการเปลี่ยนคำสั่งในโค้ดไปแล้ว หรือว่านี่คือบั๊กของ Instant Run กันนะ?

        ซึ่งจริงๆแล้ว Instant Run ทำงานถูกต้องแล้วครับ แต่ Dev ต่างหากที่ไม่เข้าใจการทำงานของ Instant Run เพราะสิ่งที่เกิดขึ้นในตัวอย่างนี้คือ Hot Swap ซึ่ง Hot Swap จะอัปเดตโค้ดใหม่เข้าไปแล้ว Override แทนที่ของเก่าทันที โดยที่ Activity ยังคงทำงานอยู่เหมือนเดิม ไม่มีการ Restart Activity

        เมื่อ Hot Swap ไม่มีการ Restart Activity แล้ว onCreate จะทำงานใหม่อีกครั้งหรือป่าว?

        นั่นล่ะครับคือสิ่งที่เกิดขึ้น เพราะ Hot Swap ไม่ทำให้ Activity ถูก Restart ก็เลยทำให้ onCreate ไม่ถูกเรียกใช้งานซ้ำนั่นเอง จึงเป็นสาเหตุว่าแก้ไขโค้ดที่ผูกไว้กับ onCreate แล้วไม่เกิดการเปลี่ยนแปลงเมื่อใช้ Instant Run

        เพราะงั้นถ้าผู้ที่หลงเข้ามาอ่านเคยเจอปัญหาคล้ายๆกันแบบนี้ ลองเช็คใหม่ดูครับว่าจริงๆแล้วเป็นเพราะ Hot Swap มันไม่ Restart Activity หรือป่าว?

        จนล่าสุดทางทีม Android Studio จึงต้องใส่ปุ่มตั้งค่าเพิ่มมาอีกหนึ่งปุ่ม นั่นก็คือบังคับให้ Activity ทำการ Restart ใหม่ทุกครั้งไปเลย

        เพราะงั้นแนะนำให้เข้าไปกดเปิดละกันครับ...


        กรณีที่สองคือ เวลาที่เกิด Warm Swap (หรือสั่งให้ Activity Restart ทุกครั้ง) สิ่งที่เกิดขึ้นคือ Activity ถูกทำลายลง และในระหว่างที่ถูกทำลายก็จะเก็บค่าต่างๆไว้ และเมื่อเริ่มทำงานใหม่อีกครั้งก็จะคืนค่าที่เก็บไว้กลับมา

       Save/Restore Instance State นั่นเอง!!


        เพื่อที่ว่าแอปฯจะได้ทำงานต่อเนื่องจากของเดิมได้ทันทีที่เกิด Warm Swap ซึ่งคำตอบที่เจ้าของบล็อกอยากจะถามก็คือ

        แล้วแอปฯของผู้ที่หลงเข้ามาอ่านจัดการกับ Instance State เหล่านั้นอย่างถูกต้องแล้วหรือยัง?

        ถ้าผู้ที่หลงเข้ามาอ่านยังไม่ได้ทำอะไรเลย สิ่งที่เกิดขึ้นคือเมื่อเกิด Warm Swap เมื่อไร ก็จะทำให้ Instance ทุกตัวถูกเคลียร์ทิ้งไปเลย ในขณะที่ View ต่างๆของแอนดรอยด์ยังคงสามารถจัดการเรื่องนี้ให้อยู่

        ดังนั้นหัวใจสำคัญคือ แอปฯควรจัดการกับ Instance State ด้วยเพื่อที่จะได้ Warm Swap

        ถ้าผู้ที่หลงเข้ามาอ่านคนใดไม่รู้จัก จงเข้าไปอ่านกันที่ [Android Code] มา Save/Restore กับ Instance State บน Activity ให้ถูกต้องกันเถอะ

และเรื่องเล่าหนึ่งเรื่องจาก Instant Run

        เนื่องจาก Instant Run ถูกเปิดใช้งานทันทีใน Android Studio เวอร์ชันหลังๆมานี้ เพื่อที่ว่า Dev จะได้ใช้งานได้ทันที โดยไม่ต้องไปนั่งเปิดใช้งานเองทุกครั้ง

        แต่นั่นก็ไม่ใช่เรื่องดีซักเท่าไหร่... เพราะยังมี Dev อีกหลายๆคนที่ยังไม่รู้ว่ามันมีฟีเจอร์นี้อยู่ และอาจจะไม่รู้ว่าตัวเองใช้ฟีเจอร์นี้อยู่ด้วยซ้ำ ซึ่งมักจะเกิดขึ้นกับ Dev มือใหม่ที่เริ่มต้นบน Android Studio ที่มีฟีเจอร์นี้มาตั้งแต่แรกอยู่แล้วโดยที่ไม่รู้ตัว

        ซึ่งเรื่องนี้เกิดขึ้นกับน้องคนหนึ่งที่ส่ง Resume พร้อมกับแนบไฟล์ APK เพื่อสมัครงาน ณ บริษัทแห่งหนึ่ง ก็ฟังดูเป็นเรื่องปกติของการสมัครงานตำแหน่ง Developer แหละเนอะ

        แต่ทว่า APK ที่ส่งมานั้นกลับเปิดไม่ได้ พอติดตั้งลงในอุปกรณ์แอนดรอยด์แล้วเปิดขึ้นมาก็จะ Force Close ทันที คงรู้กันอยู่แล้วว่าการสมัครงานของ Dev สิ่งสำคัญอย่างหนึ่งในการสมัครคือผลงานที่เคยทำ แต่จะเป็นยังไงถ้าผลงานที่แนบไปด้วยเกิดใช้งานไม่ได้ขึ้นมา?

        แล้วมันเกี่ยวอะไรกับ Instant Run ล่ะเนี่ย?

        พออ่านมาถึงตรงนี้ ผู้ที่หลงเข้ามาอ่านก็อาจจะเริ่มงงแล้วว่าเจ้าของบล็อกจะเล่าทำมะเขือเผือกอะไร นี่มันบทความ Instant Run นะ ไม่ใช่บทความสมัครงาน

        แต่ปัญหาที่เกิดขึ้น เกิดมาจาก Instant Run นั่นแหละครับ

        เมื่อ APK ตัวนั้นใช้งานไม่ได้ คนที่ดูผลงานของ Dev คนนั้นก็แอบไปเปิด APK ดูว่ามีปัญหาอะไร ทำไมถึงเปิดไม่ได้ และก็พบกับภาพนี้


        อาจจะดูเหมือนข้างในไฟล์ APK ปกติทั่วไปเนอะ แต่ให้ลองสังเกตที่ไฟล์ instant-run.zip ดีๆ ครับ เพราะปกติมันจะไม่มีไฟล์นี้อยู่ใน APK

        ซึ่ง APK ตัวนี้ถูกสร้างขึ้นจาก Instant Run เพื่ออัปเดตโค้ดเฉพาะส่วนเท่านั้น ซึ่งเมื่อเปิดไฟล์ดังกล่าวดูก็จะพบกับคลาสต่างๆที่ถูกจัดเก็บไว้เพื่อให้ Instant Run ยัดเข้าอุปกรณ์แอนดรอยด์ที่เปิดแอปฯตัวนั้นอยู่


        นั่นก็หมายความว่าโค้ดหลายๆส่วนของแอปฯนั้นถูกยัดเก็บไว้ในไฟล์ตัวนี้ไว้อยู่ เพื่อที่จะอัปเดตตามขั้นตอนของ Instant Run

        การที่ Dev คนนั้นเจอปัญหานี้ นั่นก็หมายความว่า APK ที่เอามาแนบคู่กับ Resume นั้นเอามาจากที่...


        ซึ่ง APK ที่ถูกสร้างขึ้นตอน Debug (หรือกด Run จาก Android Studio นั่นแหละ) ก็อาจจะใช้สำหรับ Instant Run เท่านั้น ยังไม่สามารถเอาไปใช้งานจริงได้ แต่ Dev ส่วนใหญ่ก็จะไม่รู้ เพราะตอน Debug ลงเครื่องตัวเอง มันก็สามารถทำงานได้ปกติ นั่นก็เพราะมี APK ตอน Full Build ติดตั้งอยู่ตั้งแต่ตอนเริ่มต้นแล้วนั่นเอง

        จริงๆมันก็ผิดตั้งแต่ตรงที่เอา Debug App มาส่งแล้วล่ะ... อย่างน้อยก็ควร Build เป็น Release ออกมาส่งให้คนอื่นมากกว่านะ...


สรุป

        Instant Run เป็นฟีเจอร์หนึ่งใน Android Studio ที่จะเข้ามาช่วยเปลี่ยนชีวิตของ Dev ให้ดียิ่งขึ้น ลดระยะเวลาในการ Build ลงซึ่งเป็นหนึ่งในสาเหตุหลักที่ทำให้สิ้นเปลืองเวลาในการพัฒนาโปรเจคซักตัว แต่ถึงกระนั้น Instant Run ก็มีเบื้องหลังที่ค่อนข้างซับซ้อนพอสมควรที่ Dev จะต้องทำความเข้าใจกับการทำงานของมันเสียก่อนถึงจะใช้งานได้ดี แต่ในความเป็นจริงก็มี Dev บางส่วนที่ยังไม่รู้ว่ามีความสามารถนี้ด้วยซ้ำ ฮาๆ พอไม่เข้าใจการทำงานของมัน เวลาใช้งานแล้วพบปัญหาก็ไม่รู้ว่าเป็นเพราะอะไร จึงทำให้ส่วนใหญ่เลือกที่จะปิดใช้งานไป หรือบ้างก็ไม่รู้จักก็เลยต้องใช้วิธี Clean Project ใหม่ทุกครั้ง

        เจ้าของบล็อกก็คงแนะนำว่าอยากให้ Android Dev ควรจะต้องรู้จักกับ Instant Run แล้วล่ะ เพราะมันติดมากับ Android Studio ตั้งแต่แรก ถ้าไม่ได้ใช้งานมัน ก็จะไปเข้าลูปเดิมๆของการ Build Gradle ที่ทำให้สิ้นเปลืองเวลา แต่ถ้าใช้งานมันก็ควรจะต้องทำความเข้าใจการทำงานของมันก่อน เพื่อให้สามารถใช้ได้อย่างไม่มีปัญหา เพราะปัญหาหลักๆที่ส่วนใหญ่เจอกันก็คือ ไม่เข้าใจการทำงานของ Hot Swap และไม่ได้จัดการกับ Instance State ให้ถูกต้องตั้งแต่แรกอยู่แล้ว

        ซึ่งจากการลองใช้งานจริงๆ เจ้าของบล็อกก็พบว่า Instant Run มันตอบโจทย์การทำงานได้ค่อนข้างดีครับ เจ้าของบล็อกสามารถเขียนโค้ดแล้วรับ Feedback ได้ไวขึ้น ทำให้ย่นระยะเวลาในการทำงานไปได้พอสมควร แต่การทำงานของ Instant Run ก็อาจจะยังไม่สมบูรณ์ 100% โดยเฉพาะกับโปรเจคใหญ่มากๆ ซึ่งอันนั้นก็ต้องยอมปิดใช้งานไป แต่สำหรับโปรเจคทั่วไปแล้วเจ้าของบล็อกก็แนะนำให้ลองใช้งานดูครับ

        และอย่าไปส่งไฟล์ Debug App เวลาสมัครงานนะ...

แหล่งข้อมูลเพิ่มเติม

        • Instant Run: How Does it Work?! @ Medium
        • About Instant Run @ Android Developer
        • Instant Run: An Android Tool Time Deep Dive @ YouTube