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

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

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

// AwesomeApplication.java
class AwesomeApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        Hawk.init(baseContext).build()
    }
}

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

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

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

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

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

  • เป็น Component แรกสุดที่ถูกสร้างขึ้นมาเมื่อผู้ใช้เปิดแอปพลิคชันขึ้นมาในครั้งแรก ก่อนที่ Activity, Service และ Broadcast Receiver จะทำงานเสียอีก
  • การสร้าง Content Provider จะต้องประกาศ <provider /> ใน Android Manifest ซึ่งจะถูกรวมไว้ใน Android Manifest ของ Module หลักโดยอัตโนมัติเมื่อ Build เป็น APK

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

// AwesomeContentProvider.kt
class AwesomeApplication : 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 ตั้งแต่แรกเลย จะได้ไม่ต้องให้นักพัฒนาคนอื่นต้องไปนั่งประกาศคำสั่งเอง

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