9.4. 重构 UpdaterService

优质
小牛编辑
127浏览
2023-12-01

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

}

  1. 我们需要多次用到db和dbHelper两个对象,因此把它们定义为类的成员变量。
  2. Android中的Service本身就是Context的子类,因此可以通过this创建DbHelper的实例。DbHelper可在需要时创建或者升级数据库。
  3. 连接到服务端并获取最新的Timeline,插入数据库。 先通过YambaApplication中的getTwitter()获取Twitter对象,然后使用getFriendsTimeline()调用 Twitter API 获取24小时内最新的20条消息。
  4. 获取写入模式的数据库对象。在第一次调用时,将触发DbHelper的onCreate()方法。
  5. ContentValues是一种简单的键值对结构,用以保存字段到数据的映射。
  6. 遍历所得的所有数据。这里使用了 Java 的 for-each 语句来简化迭代过程。
  7. 为每条记录分别生成一个ContentValues。这里我们重用了同一个对象:在每次迭代中,都反复清空它,然后绑定新的值。
  8. 调用insert()将数据插入数据库。留意在这里我们并没有使用任何SQL语句,而是使用了既有的封装。
  9. 最后不要忘记关闭数据库。这很重要,不然会无谓地浪费资源。

一切就绪,准备测试。