すでにApplicationを継承したクラスがある場合に、Google Analytics関連のメソッドなどを追加でどう定義するか
現在アプリでVolleyを使用していて、それ関連はextends Applicationしたクラス
にまとめてあります。
この度Google Analyicsを導入することになり公式を参考に取り組んでいるのですが、それ用のTrackerの取得をVolley同様extends Applicationしたクラス
に書くよう書かれています。
Volley関連はシングルトンがよく、Analytics関連はContextが使えるシングルトンがよいからどちらもextends Applicationしたクラス
に定義することを望んているのだと思いますが、そのクラスは2つも作れないと思います。
実際に私が定義しているVolley関連のクラスにはContextを使用しているコードはなさそうだったので、サンプルによくあるコードのようにextends Applicationしたクラス
にしなくても普通のシングルトンでよかったかもしれませんが、今更の変更はテスターの負担増になるので避けたいと思っています。
ですが、Volley関連とAnalytics関連を同一ではなく別クラスで管理したいと考えています。
そこでAnalytics関連のクラスの設計について以下の3パターンを考えたのですが、どれが良いでしょうか?
もしくは他の設計の方が良いでしょうか?
- 普通のシングルトンで定義してTrackerを取得するメソッドの引数にContextを渡す
公式のサンプルのような同一のトラッカーを使い回すことを考えると、2回目以降は無駄にContextを渡していることになる。 - Volley関連のクラスのみでインスタンスを生成するようにした擬似シングルトンで定義する
生成時にContextを渡してTrackerを作るので無駄にContextを渡すなんてことはないが、設計としていまいちでは。 - Volley関連のクラスをextendsしたクラスを定義する
そうすればextends Applicationと同義にはなるとは思うが、このような設計はやってはいけない気がする。
追記
現在のApplicationクラスの実装は次のようになっています。
(package宣言は消しています。)
import android.app.Application;
import android.graphics.Bitmap;
import android.util.LruCache;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;
import de.greenrobot.event.EventBus;
/**
* キューでリクエストを管理するためのクラス.
*
* Applicationを拡張して作ったシングルトンクラス。
*
* @see android.app.Application Application
*/
public class AppController extends Application {
public static final String TAG = AppController.class.getSimpleName();
private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
private static AppController sInstance;
/**
* AndroidManifest.xmlのandroid:name項目によりインスタンスが作成されて呼び出される.
*/
@Override
public void onCreate() {
super.onCreate();
sInstance = this;
}
/**
* シングルトロンクラスのためのインスタンス取得用メソッド.
*
* @return このクラスのインスタンス
*/
public static synchronized AppController getInstance() {
return sInstance;
}
/**
* リクエストキューを取得するためのメソッド.
*
* @return リクエストキュー
*/
private RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
/**
* イメージローダーを取得するためのメソッド.
*
* @return イメージローダー
*/
public ImageLoader getImageLoader() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
if (mImageLoader == null) {
mImageLoader = new ImageLoader(mRequestQueue, new ImageLruCache());
}
return mImageLoader;
}
/**
* 画像をキャッシュするためのクラス.
*/
public static class ImageLruCache implements ImageLoader.ImageCache {
private LruCache mMemoryCache;
public ImageLruCache() {
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
int cacheSize = maxMemory / 8;
mMemoryCache = new LruCache(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);
}
}
/**
* リクエストをキューに追加するためのメソッド.
*
* @param req 行う処理を定義したリクエスト
* @param
*/
public void addToRequestQueue(Request req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
/**
* 保留中のリクエストをキャンセルするためのメソッド.
*
* @param tag キャンセルしたい保留中のリクエストのタグ
*/
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
/**
* Volleyのエラー時に呼び出すメソッド.
*
* @param error Volleyのエラー内容
*/
public void onErrorResponse(VolleyError error) {
if (error.networkResponse == null) {
EventBus.getDefault().post(new UserEvent(UserEvent.Id.CONNECTION_ERROR, ""));
} else {
EventBus.getDefault().post(new UserEvent(UserEvent.Id.CONNECTION_ERROR, String.valueOf(error.networkResponse.statusCode)));
}
}
}