8.4. 从 Twitter 读取数据
8.4.从 Twitter 读取数据
我们已经有了个大体的框架,接下来就连接到 Twitter ,读取数据并且在程序中显示出来。Twitter 或者其他的微博平台提供的 API 都各不相同。这时可以使用三方库jtwitter.jar,它提供了一个Twitter类作为封装。里边最常用的功能之一就是getFriendsTimeline(),它可以返回24小时中自己和朋友的最新20条消息。
要使用 Twitter API 的这一特性,首先应连接到 Twitter 服务。我们需要一个用户名、密码,以及一个API授权。回忆下本章前面 “Yamba 的 Application 对象” 一节中,我们已经把大部分相关的功能重构到了 YambaApplication 中。因此我们得以在这里重用这一功能,因为包括 Service 在内的程序中任何一个构件,都可以访问同一个 Application 对象。
在这里我们需要小小地修改下 YambaAppliaction ,好让别人知道这个 Service 是否正在运行。因此在 YambaApplication 中添加一个标志变量,配合 getter 与 setter 用以访问与更新:
public class YambaApplication extends Application implements OnSharedPreferenceChangeListener {
private boolean serviceRunning; //
...
public boolean isServiceRunning() { //
return serviceRunning;
}
public void setServiceRunning(boolean serviceRunning) { //
this.serviceRunning = serviceRunning;
}
}
- 这个标志变量表示了 Service 的运行状态。注意它是个私有成员,不可以直接访问。
- 这个全局方法用以访问标志变量serviceRunning的值。
- 另一个全局方法,用以设置标志变量serviceRunning的值。
接下来我们可以为UpdaterService写些代码,让它连接到API,读取朋友的最新消息。
例 8.6. UpdaterService.java, final version
package com.marakana.yamba3;
import java.util.List;
import winterwell.jtwitter.Twitter;
import winterwell.jtwitter.TwitterException;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class UpdaterService 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; //
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
this.yamba = (YambaApplication) getApplication(); //
this.updater = new Updater();
Log.d(TAG, "onCreated");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
this.runFlag = true;
this.updater.start();
this.yamba.setServiceRunning(true); //
Log.d(TAG, "onStarted");
return 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() {
UpdaterService updaterService = UpdaterService.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); //
}
// Loop over the timeline and print it out
for (Twitter.Status status : timeline) { //
Log.d(TAG, String.format("%s: %s", status.user.name, status.text)); //
}
Log.d(TAG, "Updater ran");
Thread.sleep(DELAY);
} catch (InterruptedException e) {
updaterService.runFlag = false;
}
}
}
} // Updater
}
- 这个变量用以方便访问YambaApplication对象,便于使用其中的共享功能,比如读取用户设置、连接到远程服务等。
- 通过getApplication()方法获得YambaApplication对象的引用。
- 一旦启动了这个 Service ,我们就设置YambaApplication中的标志变量serviceRunning。
- 同样,等 Service 停止时也修改YambaApplication对象中的serviceRunning。
- 我们使用了 Java 中的泛型来定义一个存放Twitter.Status的 List 变量。
- 调用YambaApplication中的getTwitter()方法获得 Twitter 对象,然后调用getFriendTimeline()来获得24小时内朋友最新的20条消息。注意因为这个函数需要访问云端服务,所以其运行时间受网络延迟影响比较大。我们把它安置在一个独立的线程中,从而防止它拖慢用户界面的响应。
- 网络相关的操作失败的原因有很多。我们在这里捕获异常,并打印出错时的堆栈信息。其输出在 Logcat 中可见。
- 现在我们已经初始化了 timeline这个 List ,可以遍历其中的元素。最简单的方法就是使用 Java 的 "foreach" 循环,自动地遍历我们的 List ,分别把每个元素的引用交给变量 status。
- 暂时我们先把消息也就是“谁说了什么“输出到 Logcat。