11.3. TimelineReceiver
11.3.TimelineReceiver
目前,UpdaterService可以定期抓取最新的消息数据,但它无法通知TimelineActivity。因此Timeline界面仍不能做到即时更新。
为解决这一问题,我们将创建另一个BroadcastReceiver,使它作为TimelineActivity的内部类。
例 11.4. TimelineActivity.java,内部类TimelineReceiver
...
class TimelineReceiver extends BroadcastReceiver { //
@Override
public void onReceive(Context context, Intent intent) { //
cursor.requery(); //
adapter.notifyDataSetChanged(); //
Log.d("TimelineReceiver", "onReceived");
}
}
...
- 同前面一样,BroadcastReceiver都是以BroadcastReceiver作为基类。
- 唯一需要实现的方法是onReceive()。其中的代码会在Receiver被触发时执行。
- 通知cursor对象刷新自己。对此,只需调用requery()方法,重新执行它的上一次数据查询就可以了。
- 通知adapter对象,它的内部数据已经被修改。
要让Receiver正常工作,我们还需要将它注册。不过这里不像刚才的BootReceiver那样在Manifest文件中添加声明就好,我们需要动态地注册TimelineReceiver。因为TimelineReceiver仅在用户查看 Timeline 界面时才有意义,将它静态地注册到Manifest文件的话,会无谓地浪费资源。
例 11.5. TimelineActivity.java中的内部类TimelineReceiver
...
@Override
protected void onResume() {
super.onResume();
// Get the data from the database
cursor = db.query(DbHelper.TABLE, null, null, null, null, null,
DbHelper.C_CREATED_AT + " DESC");
startManagingCursor(cursor);
// Create the adapter
adapter = new TimelineAdapter(this, cursor);
listTimeline.setAdapter(adapter);
// Register the receiver
registerReceiver(receiver, filter); //
}
@Override
protected void onPause() {
super.onPause();
// UNregister the receiver
unregisterReceiver(receiver); //
}
...
- 在TimelineActivity进入 Running 状态时注册 Receiver 。前面在"Running状态"一节中曾提到,在Activity进入Running状态之前,肯定要经过onResume()。因此,这里是注册Receiver的好地方。
- 与之相对,Activity在进入Stopped状态之前,肯定会经过onPause()。可以在这里注销Receiver。
前面还剩一个filter对象没解释:它是一个IntentFilter的实例,用以过滤出Receiver感兴趣的事件。在这里,我们通过一条表示Action事件的字符串来初始化它。
例 11.6. TimelineActivity.java,修改后的 onCreate()
...
filter = new IntentFilter("com.marakana.yamba.NEW_STATUS"); //
...
- 创建IntentFilter的实例,以"com.marakana.yamba.NEW_STATUS"作为构造函数的参数,表示一条Action事件。在这里使用了一个字符串,以后可以将它定义成常量,方便在其它地方使用。