TL;DR
Application
クラスを継承した MyApplication
クラスを定義して、シングルトンパターンでオブジェクトを取得できるようにする。 MyApplication
オブジェクト経由で RequestQueue
オブジェクトへのアクセスを行うようにする。
概要
Volley は 2013 年の Google I/O で発表されたライブラリで、シンプルながらも強力な API を備えた便利なライブラリです。この Volley ですが、いざ使おうと思って調べてみると RequestQueue はシングルトン的に使う方が良い というような情報がいくつか出てきますが、実際どうやってシングルトン的に扱うのかが最初判りませんでした。
色々やった結果、 Application
クラスを継承したクラスを作ってあげて、アプリケーションの起動時にオブジェクトを生成し、Application
経由で RequestQueue
を取得するようにするとうまくいきました。
MyApplication.java
package net.imthinker.android.volley;
import android.app.Application;
import android.content.Context;
import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;
public class MyApplication extends Application {
private static MyApplication MY_APPLICATION;
private static Context sContext;
private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
public static MyApplication getInstance() {
if (MY_APPLICATION == null) {
MY_APPLICATION = new MyApplication();
MY_APPLICATION.setRequestQueue();
}
return MY_APPLICATION;
}
@Override
public void onCreate() {
super.onCreate();
sContext = getApplicationContext();
MY_APPLICATION = new MyApplication();
MY_APPLICATION.setRequestQueue();
}
/**
* Application Context を取得する
*
* @return Context オブジェクト
*/
public Context getContext() {
if (sContext == null) {
sContext = getApplicationContext();
}
return sContext;
}
/**
* RequestQueue を取得する
*
* @return RequestQueue オブジェクト
*/
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
setRequestQueue();
}
return mRequestQueue;
}
/**
* ImageLoader を取得する
*
* @return ImageLoader オブジェクト
*/
public ImageLoader getImageLoader() {
if (mRequestQueue == null) {
setRequestQueue();
} else if (mImageLoader == null) {
mImageLoader = new ImageLoader(mRequestQueue, new ImageLruCache());
}
return mImageLoader;
}
/**
* Volley の RequestQueue と ImageLoader を初期化する
*/
private void setRequestQueue() {
mRequestQueue = Volley.newRequestQueue(getContext());
mImageLoader = new ImageLoader(mRequestQueue, new ImageLruCache());
}
/**
* 画像のキャッシュを行う LruCache
* ※ 参考: http://qiita.com/gari_jp/items/829a54bfa937f4733e29
*/
public static class ImageLruCache implements ImageLoader.ImageCache {
private LruCache<String, Bitmap> mMemoryCache;
public ImageLruCache() {
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
int cacheSize = maxMemory / 8;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
return bitmap.getByteCount() / 1024;
}
};
}
@Override
public Bitmap getBitmap(String url) {
return mMemoryCache.get(url);
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
mMemoryCache.put(url, bitmap);
}
}
}
AndroidManifest.xml (抜粋)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.imthinker.android.volley">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
あとは MyApplication.getInstance().getRequestQueue();
でリクエストキューを取得できるので、 Volley を使った通信が必要な場面で呼び出して、キューに Request
オブジェクトを詰め込んで行く感じです。 ImageLoader
に関しても同様です。 ListView
の上にネットワークから取得した画像を載せる場合、 ImageLoader
を使ってあげると Volley が上手にキャッシュしながら非同期で読み込んでくれるので便利です。
修正
- 2014/07/27 17:27 頂いたコメントを元に修正 & タイポを修正
- 2014/07/28 11:06 嘘つきになっていた箇所を修正
- 2015/02/24 12:09 全体的に見直し