ช่วงนี้เราจะเห็นว่ามีคนเอา Library เกี่ยวกับ EventBus มาเขียนบทความกันบ่อยๆ ตัวนึงที่เห็นบ่อยมากๆ เลยคือ Otto ของ Square ซึ่งเรามักจะเอามาใช้ในการสื่อสารระหว่าง Fragment เพื่อลดความปวดหัวในการเขียน Code แต่ EventBus ก็ยังมีตัวอีกตัวที่น่าสนใจเหมือนกันนั่นก็คือ EventBus ของ GreenRobo ซึ่งเราจะมาดูกัน
EventBus ของ GreenRobo นั่นโดยหลักการแล้วก็คล้ายๆกับ Otto คือมีการ Post ข้อมูลเพื่อ Broadcast แล้วก็มีตัว Subscribe เพื่อรับข้อมูล ซึ่งจะต่างจาก Otto ตรงที่ EventBus สามารถส่งข้อมูลได้ทั้ง MainThread และ BackgroundThread
ถ้าใครอยากรู้ว่า Otto กับ EventBus ต่างกันอย่างไรแบบเต็มๆ สามารถดูได้ที่ Comparison with Square’s Otto
ไหนๆเราก็จะทำความรู้จักกับเจ้า EventBus กันแล้ว เรามาลองดูตัวอย่างการใช้งานง่ายๆกันดีกว่า ผมจะใช้ตัวอย่างจากเว็บ http://code.tutsplus.com/ ซึ่งจะเป็นการใช้ EventBus ส่ง Event เวลาเราเสียบสายชาร์จมาแสดงที่ TextView มาลองทำกันเลยดีกว่า
เริ่มแรกก็ใส่ Library เข้าไปใน gradle ก่อน
[xml]
compile ‘de.greenrobot:eventbus:2.4.0’
[/xml]
จากนั้นเราก็มาสร้าง class สำหรับทำเป็น Event กันโดยให้ชื่อว่า ChargingEvent (ตั้งยังไงก็ได้นะครับ) โดยจะเป็น String เพื่อเอาไว้บอกสถานะว่าตอนนี้เสียบสายชาร์จอยู่หรือไม่
[java]
public class ChargingEvent {
private String data;
public ChargingEvent(String data){
this.data = data;
}
public String getData(){
return data;
}
}
[/java]
ต่อมาเมื่อเรามี Event แล้ว เราก็ทำตัว Receiver เพื่อรับสถานะการเสียบเลยชาร์จกันเลยดีกว่า โดย class ChargingReceiver จะทำงานเมื่อมีการเสียบสายชาร์จ เดี๋ยวเราจะไปเพิ่ม intent-filter กันใน AndroidManifest.xml กันอีกที
[java]
public class ChargingReceiver extends BroadcastReceiver {
private EventBus bus = EventBus.getDefault();
@Override
public void onReceive(Context context, Intent intent) {
ChargingEvent event = null;
// Get current time
Time now = new Time();
now.setToNow();
String timeOfEvent = now.format("%H:%M:%S");
String eventData = "@" + timeOfEvent + " this device started ";
if (intent.getAction().equals(Intent.ACTION_POWER_CONNECTED)) {
event = new ChargingEvent(eventData + "charging.");
} else if (intent.getAction().equals(Intent.ACTION_POWER_DISCONNECTED)) {
event = new ChargingEvent(eventData + "discharging.");
}
// Post the event
bus.post(event);
}
}
[/java]
เนื่องจาก EventBus เป็น singleton จึงต้องใส่ EventBus.getDefault() ทุกครั้งก่อนใช้งาน เวลาจะใช้งานเราก็เอา ChargingEvent โยนใส่ bus.post เข้าไปเท่านี้เราก็จะส่ง Event ออกไปยัง Class อื่นๆได้แล้ว
เมื่อมีตัวส่งแล้วก็ต้องมีตัวรับ ผมขอใช้ class MainActivity นี่แหละครับ โดยเราจะรับเอา Event มาจาก onEvent(ChargingEvent event)
***สำคัญมาก อย่าลืมใส่ bus.register(this); ใน onResume() และ bus.unregister(this); ใน onPause() มิฉะนั้นจะรับ Event ไม่ได้และเกิดอาการแอพเด้ง
private EventBus bus = EventBus.getDefault();
private TextView textDisplay;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textDisplay = (TextView) findViewById(R.id.text_displayevent);
}
@Override
protected void onResume() {
bus.register(this);
super.onResume();
}
@Override
protected void onPause() {
bus.unregister(this);
super.onPause();
}
public void onEvent(ChargingEvent event){
textDisplay.setText(textDisplay.getText() + "\n" + event.getData());
}
}
[/java]
เท่านี้เราก็มีทั้งตัวส่งตัวรับแล้ว แต่อย่าลืมไปใส่ใน AndroidManifest.xml ให้ filter event การเสียบสายชาร์จด้วย
[xml]
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".ChargingReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
</intent-filter>
</receiver>
</application>
[/xml]
Run แล้วลองเสียบสายชาร์จเข้าๆออกๆดูครับ จะแสดงข้อความแบบนี้
จะเห็นว่าการใช้ EventBus จะลดการเขียน Code ไปได้มาก (และเพิ่มเวลานอนให้กับ Developer) ถ้าเป็นเมื่อก่อนกว่าจะเขียนให้ส่ง Event มาแบบนี้ได้คงต้องเขียน BroadcastReceiver กันจนเหนื่อยเลย
หากใครสนใจเจ้า EventBus สามารถเข้าไปอ่าน Document หรือใน Github ได้เลยครับ
บทความที่น่าสนใจ
การทำ In-App Billing แบบง่ายๆด้วย Library
A/B Testing in Google Play Store
ทำชีวิตให้ง่ายด้วย Build Variants
ตัวอย่างการใช้ Vibrator ใน Android