18 March 2018

ทำ Auto Initialize ให้กับ Library แบบเท่ๆกันเถอะ

Updated on


        แหม่ ไม่ได้เขียนบทความตั้งนาน คิดถึงจัง วันนี้ก็เลยหยิบเทคนิคน่าสนใจที่เจ้าของบล็อกไปอ่านเจอในบทความของ Firebase ว่าด้วยวิธีแก้ปัญหา Library หรือ SDK ที่ต้องมานั่งเรียกคำสั่งเพื่อ Initialize กัน

เมื่อต้องใช้ Library ซักตัวแล้วต้อง Initialize ใน Application Class

        สมมติว่าเจ้าของบล็อกจะหยิบ Library ที่ชื่อว่า Hawk มาใช้งานในโปรเจค และพอไปอ่าน Readme ใน GitHub ของ Library ตัวนี้ก็พบว่าจะต้องประกาศไว้ใน Application Class แบบนี้

// AwesomeApplication.java

public class AwesomeApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Hawk.init(context).build();
    }
}

         กลายเป็นว่าทุกๆครั้งที่เจ้าของบล็อกจะใช้ Library ใดๆก็ตามที่ต้องทำการ Initialize แบบนี้ ก็จะต้องมาสร้าง Application Class  ขึ้นมาเองทุกครั้งเพื่อให้คำสั่งเหล่านี้ถูกเรียกไว้ใน onCreate()

        ที่ต้องทำแบบนี้ก็เพราะว่า Hawk นั้นเป็น Library ที่ถูกออกแบบมาให้เรียกใช้งานในรูปแบบ Static Method แต่ว่าตัวมันต้องใช้ Context ในทำงาน จะให้โยน Context เข้ามาให้ทุกครั้งที่เรียกใช้งานก็ใช่เรื่อง นักพัฒนาก็เลยออกแบบให้โยน Context เข้าไปเก็บไว้ในตอนแรก เมื่อเรียกใช้งานหลังจากนั้นก็จะไปดึง Context ที่เคยเก็บไว้มาเรียกใช้งาน

        แต่จะดีกว่ามั้ยถ้าสามารถโยน Context เข้าไปได้เลยตอนที่แอปพลิเคชันเปิดขึ้นมา โดยไม่ต้องสร้าง Application Class ขึ้นมาเอง (ทำ Auto Initialize นั่นเอง)

แก้ปัญหาได้ง่ายๆด้วย Content Provider

        เดิมทีนั้น Content Provider เป็นหนึ่งใน Component พื้นฐานของแอนดรอยด์ที่ถูกสร้างขึ้นมาเพื่อเป็นตัวกลางในการเข้าถึงข้อมูล โดยมีรูปแบบการทำงานดังนี้

        • Content Provider นั้นเป็น Component แรกสุดที่ถูกสร้างขึ้นมาเมื่อผู้ใช้เปิดแอปพลิคชันขึ้นมาในครั้งแรก ก่อนที่ Activity, Service และ Broadcast Receiver จะทำงานเสียอีก

        • การสร้าง Content Provider จะต้องประกาศ <provider /> ใน Android Manifest ซึ่งจะถูกรวมไว้ใน Android Manifest ของ Module หลักโดยอัตโนมัติเมื่อ Build เป็น APK

        ด้วยรูปการทำงานทั้ง 2 แบบนี้ จึงสามารถเอา Content Provider มาประยุกต์เพื่อทำ Auto Initialize ได้นั่นเอง

// AwesomeContentProvider.kt

class AwesomeContentProvider : ContentProvider() {
    override fun onCreate(): Boolean {
        Hawk.init(context).build()
        return true
    }
    ...
}

// AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
    ...
    <application ...>
        ...
        <provider
            android:name=".AwesomeContentProvider"
            android:authorities="com.akexorcist.awesome.provider"
            android:exported="false" />
    </application>
</manifest>

        โดยชื่อ Authorities จะตั้งเป็นชื่ออะไรก็ได้ เพราะว่าไม่ได้ใช้งานในส่วนของ Content Provider

สรุป

        การใช้ Content Provider เข้ามาช่วยจัดการพวกคำสั่งจาก Library ที่จำเป็นต้อง Initialize ก่อนใช้งานทุกครั้งจะช่วยให้ผู้ที่หลงเข้ามาอ่านไม่ต้องไปนั่งสร้าง Application Class ขึ้นมาเพื่อเรียกคำสั่งเหล่านั้น  แต่ถ้าจะให้ดีกว่านั้น Library ควรใช้ Content Provider ตั้งแต่แรกเลย จะได้ไม่ต้องให้นักพัฒนาคนอื่นต้องไปนั่งประกาศคำสั่งเอง

แหล่งข้อมูลอ้างอิง

        • Content Provider [Android Developer]
        • How does Firebase initialize on Android? [The Firebase Blog]