为了提升手机端的响应速度,Foursquare采用了一种巧妙的措施,Foursquare在获取一个带图片的列表的时候,图片和文字区别对待。Foursquare先获取文字列表并显示出文字,而图片则是延迟加载。在加载图片的过程采用了缓存+多线程+线程池等技术优化读取速度。Foursquare读取图片的时候采用多线程技术,同时几个线程读取图片,并把读到的图片缓存起来,以便下次读取。读到图片以后通知界面更新。
图标读取优化是Foursquare中最为复杂的技术之一。在分析之前应该先掌握以下基础知识:
1.观察者模式。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。
详见http://baike.baidu.com/view/1854779.htm?fr=ala0_1
2.ExecutorService是java中用于管理一个线程池的类,使用实例参见
http://hi.baidu.com/coolinc/blog/item/0d5545d48c9183ce50da4bcf.html
3.Android notifyDataSetChanged() 方法:notifyDataSetChanged方法通过一个外部的方法控制如果适配器的内容改变时需要强制调用getView来刷新每个Item的内容。
图片读取主要有四个类组成FetcherObserver 是RemoteResourceFetcher的Observer,等待RemoteResourceFetcher获取的数据后调用RemoteResourceManager中的notifyObservers()通知RemoteResourceManagerObserver更新界面。
RemoteResourceFetcher 通过网络以多线程的方式获取数据。获取图片代码:
ExecutorService mExecutor;
mExecutor = Executors.newCachedThreadPool(); //创建线程池
public Future<Request> fetch(Uri uri, String hash) {
Request request = new Request(uri, hash);
synchronized (mActiveRequestsMap) {
Callable<Request> fetcher = newRequestCall(request); //构造http请求
if (mActiveRequestsMap.putIfAbsent(request, fetcher) == null) {
if (DEBUG) Log.d(TAG, "issuing new request for: " + uri);
return mExecutor.submit(fetcher); //执行线程
} else {
if (DEBUG) Log.d(TAG, "Already have a pending request for: " + uri);
}
}
return null;
}
//构造的读取请求
private Callable<Request> newRequestCall(final Request request) {
return new Callable<Request>() {
public Request call() {
try {
if (DEBUG) Log.d(TAG, "Requesting: " + request.uri);
HttpGet httpGet = new HttpGet(request.uri.toString());
httpGet.addHeader("Accept-Encoding", "gzip");
HttpResponse response = mHttpClient.execute(httpGet); //执行http请求
HttpEntity entity = response.getEntity();
InputStream is = getUngzippedContent(entity);
mResourceCache.store(request.hash, is); //获取的数据存入到缓存中
if (DEBUG) Log.d(TAG, "Request successful: " + request.uri);
} catch (IOException e) {
if (DEBUG) Log.d(TAG, "IOException", e);
} finally {
if (DEBUG) Log.d(TAG, "Request finished: " + request.uri);
mActiveRequestsMap.remove(request);
notifyObservers(request.uri); //通知所有Observer 这里通知的是 FetcherObserver对象
}
return request;
}
};
}
FetcherObserver 监视RemoteResourceFetcher 并调用RemoteResourceManager
中的notifyObservers() 通知 RemoteResourceManager 中注册的Observer对象
public void update(Observable observable, Object data) {
setChanged();
notifyObservers(data); // 调用RemoteResourceManager中的notifyObservers通知RemoteResourceManagerObserver更新数据
}
RemoteResourceManager 管理缓存,并通知RemoteResourceManagerObserver
RemoteResourceManagerObserver调用更新方法更新界面
private class RemoteResourceManagerObserver implements Observer {
@Override
public void update(Observable observable, Object data) {
if (DEBUG) Log.d(TAG, "Fetcher got: " + data);
mHandler.post(new Runnable() {
@Override
public void run() {
notifyDataSetChanged(); // 通知android界面更新
}
});
}
}