9.4. 重构 UpdaterService
9.4.重构 UpdaterService
UpdaterService是负责连接到服务端并抓取数据的Service,因此由它负责将数据写入数据库是合理的。
接下来重构UpdaterService,为它添加写入数据库的相关代码。
例 9.2. UpdaterService.java, version 1
package com.marakana.yamba4;
import java.util.List;
import winterwell.jtwitter.Twitter;
import winterwell.jtwitter.TwitterException;
import android.app.Service;
import android.content.ContentValues;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.IBinder;
import android.util.Log;
public class UpdaterService1 extends Service {
private static final String TAG = "UpdaterService";
static final int DELAY = 60000; // wait a minute
private boolean runFlag = false;
private Updater updater;
private YambaApplication yamba;
DbHelper1 dbHelper; //
SQLiteDatabase db;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
this.yamba = (YambaApplication) getApplication();
this.updater = new Updater();
dbHelper = new DbHelper1(this); //
Log.d(TAG, "onCreated");
}
@Override
public int onStartCommand(Intent intent, int flag, int startId) {
if (!runFlag) {
this.runFlag = true;
this.updater.start();
((YambaApplication) super.getApplication()).setServiceRunning(true);
Log.d(TAG, "onStarted");
}
return Service.START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
this.runFlag = false;
this.updater.interrupt();
this.updater = null;
this.yamba.setServiceRunning(false);
Log.d(TAG, "onDestroyed");
}
/**
* Thread that performs the actual update from the online service
*/
private class Updater extends Thread {
List<Twitter.Status> timeline;
public Updater() {
super("UpdaterService-Updater");
}
@Override
public void run() {
UpdaterService1 updaterService = UpdaterService1.this;
while (updaterService.runFlag) {
Log.d(TAG, "Updater running");
try {
// Get the timeline from the cloud
try {
timeline = yamba.getTwitter().getFriendsTimeline(); //
} catch (TwitterException e) {
Log.e(TAG, "Failed to connect to twitter service", e);
}
// Open the database for writing
db = dbHelper.getWritableDatabase(); //
// Loop over the timeline and print it out
ContentValues values = new ContentValues(); //
for (Twitter.Status status : timeline) { //
// Insert into database
values.clear(); //
values.put(DbHelper1.C_ID, status.id);
values.put(DbHelper1.C_CREATED_AT, status.createdAt.getTime());
values.put(DbHelper1.C_SOURCE, status.source);
values.put(DbHelper1.C_TEXT, status.text);
values.put(DbHelper1.C_USER, status.user.name);
db.insertOrThrow(DbHelper1.TABLE, null, values); //
Log.d(TAG, String.format("%s: %s", status.user.name, status.text));
}
// Close the database
db.close(); //
Log.d(TAG, "Updater ran");
Thread.sleep(DELAY);
} catch (InterruptedException e) {
updaterService.runFlag = false;
}
}
}
} // Updater
}
- 我们需要多次用到db和dbHelper两个对象,因此把它们定义为类的成员变量。
- Android中的Service本身就是Context的子类,因此可以通过this创建DbHelper的实例。DbHelper可在需要时创建或者升级数据库。
- 连接到服务端并获取最新的Timeline,插入数据库。 先通过YambaApplication中的getTwitter()获取Twitter对象,然后使用getFriendsTimeline()调用 Twitter API 获取24小时内最新的20条消息。
- 获取写入模式的数据库对象。在第一次调用时,将触发DbHelper的onCreate()方法。
- ContentValues是一种简单的键值对结构,用以保存字段到数据的映射。
- 遍历所得的所有数据。这里使用了 Java 的 for-each 语句来简化迭代过程。
- 为每条记录分别生成一个ContentValues。这里我们重用了同一个对象:在每次迭代中,都反复清空它,然后绑定新的值。
- 调用insert()将数据插入数据库。留意在这里我们并没有使用任何SQL语句,而是使用了既有的封装。
- 最后不要忘记关闭数据库。这很重要,不然会无谓地浪费资源。
一切就绪,准备测试。