androidで、通信ライブラリのvolleyを使うことになったので、個人的メモ

Android には、volleyという通信ライブラリがある。
Volley勉強したので、そのメモを書く。

## volleyの基本

httpリクエストを送るには、RequestQueueを作り、Requestオブジェクトを渡す。

RequestQueueは、workerスレッドで働く。
レスポンスが帰ってくると、レスポンスをメインスレッドへと渡す。

まず、Volley.newRequestQueueを使い、RequestQueueを作る。


```java
final TextView textView = (TextView) findViewById(R.id.text);
// ...

// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(this);
String url ="http://www.google.com";

// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
            new Response.Listener<String>() {
    @Override
    public void onResponse(String response) {
        // Display the first 500 characters of the response string.
        textView.setText("Response is: "+ response.substring(0,500));
    }
}, new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
        textView.setText("That didn't work!");
    }
});

// Add the request to the RequestQueue.
queue.add(stringRequest);
```
このようにRequestQueueにrequestをaddするのが全ての基本になる。

## httpリクエストを送る。

httpリクエストを送るには、シンプルに、RequestQueueに、add()を使い構築する必要がある。
requestQueueにaddすることで自動的にhttpリクエストが投げられ、パースされたレスポンスがメインスレッドに帰ってくる。

```java
public static final String TAG = "MyTag";
StringRequest stringRequest; // Assume this exists.
RequestQueue requestQueue;  // Assume this exists.

// Set the tag on the request.
stringRequest.setTag(TAG);

// Add the request to the RequestQueue.
requestQueue.add(stringRequest);
```

## cacheとnetworkのセットアップ
RequestQueueには、以下の二つが必要だ。
DiskBasedCache: in-memoryのindexを使った１レスポンス＝１ファイルのキャッシュ

BasicNetwork: Volleyのデフォルトのネットワーク実行。BasicNetworkは、Httpクライアントで初期化される必要がある。
例えば、HttpURLConnectiontとかで。

以下のコードは、RequestQueueのセットアップの一例だ。

```java
RequestQueue requestQueue;

// Instantiate the cache
Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap

// Set up the network to use HttpURLConnection as the HTTP client.
Network network = new BasicNetwork(new HurlStack());

// Instantiate the RequestQueue with the cache and network.
requestQueue = new RequestQueue(cache, network);

// Start the queue
requestQueue.start();

String url ="http://www.example.com";

// Formulate the request and handle the response.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
        new Response.Listener<String>() {
    @Override
    public void onResponse(String response) {
        // Do something with the response
    }
},
    new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            // Handle error
    }
});

// Add the request to the RequestQueue.
requestQueue.add(stringRequest);

// ...
```

## singletonパターンを使おう
Applicationのサブクラス、Applicationの、onCreate()などを使う方法もあるが、RequestQueueをセットアップするのに一番適した方法は、staticなsingletonクラスを作ることだ。

重要なのはActivityのContextではなく、Applicationのcontextを使うこと。
なぜならApplicationのContextを使うことでアプリが生きている間はRequestQueueの動作が保証されるから。

```java
public class MySingleton {
    private static MySingleton instance;
    private RequestQueue requestQueue;
    private ImageLoader imageLoader;
    private static Context ctx;

    private MySingleton(Context context) {
        ctx = context;
        requestQueue = getRequestQueue();

        imageLoader = new ImageLoader(requestQueue,
                new ImageLoader.ImageCache() {
            private final LruCache<String, Bitmap>
                    cache = new LruCache<String, Bitmap>(20);

            @Override
            public Bitmap getBitmap(String url) {
                return cache.get(url);
            }

            @Override
            public void putBitmap(String url, Bitmap bitmap) {
                cache.put(url, bitmap);
            }
        });
    }

    public static synchronized MySingleton getInstance(Context context) {
        if (instance == null) {
            instance = new MySingleton(context);
        }
        return instance;
    }

    public RequestQueue getRequestQueue() {
        if (requestQueue == null) {
            // getApplicationContext() is key, it keeps you from leaking the
            // Activity or BroadcastReceiver if someone passes one in.
            requestQueue = Volley.newRequestQueue(ctx.getApplicationContext());
        }
        return requestQueue;
    }

    public <T> void addToRequestQueue(Request<T> req) {
        getRequestQueue().add(req);
    }

    public ImageLoader getImageLoader() {
        return imageLoader;
    }
}
```

以下は、RequestQueueのSingletonでの実行の一例だ。

```java
// Get a RequestQueue
RequestQueue queue = MySingleton.getInstance(this.getApplicationContext()).
    getRequestQueue();

// ...

// Add a request (in this example, called stringRequest) to your RequestQueue.
MySingleton.getInstance(this).addToRequestQueue(stringRequest);
```

## Standard request
StringRequest = raw stringとしてレスポンスを受け取る。
JsonObjectRequest, JsonArrayRequest  = Jsonまたは、Arrayとしてレスポンスを受け取る。


一例は以下だ。

```java
String url = "http://my-json-feed";

JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
        (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {

    @Override
    public void onResponse(JSONObject response) {
        textView.setText("Response: " + response.toString());
    }
}, new Response.ErrorListener() {

    @Override
    public void onErrorResponse(VolleyError error) {
        // TODO: Handle error

    }
});

// Access the RequestQueue through your singleton class.
MySingleton.getInstance(this).addToRequestQueue(jsonObjectRequest);
```

volley難しい。もっと素朴なものが欲しいな。

以上個人的メモでした。