5665


ActivityからFragmentへActivityで`Volley.NewRequestQueue()`により生成した`RequestQueue`を渡すには､Volleyの`Volley.java`と`RequestQueue.java`をそれぞれ継承したクラスを作成し､`Serializable`を実装し､`Bundle`で渡す以外の方法はありますか｡

それともフラグメント側で`Volley.newRequestQueue()`を書いてしまっても良いのでしょうか｡

よろしくお願いします｡


CC BY-SA 3.0
2015-01-30T09:59:57.860
5620
2015-01-31T12:26:52.563
7232
question
android network android-volley
FragmentにVolleyのRequestQueueを渡す｡


Googleのトレーニング用ドキュメントに、`Application`クラスに持たせる例が示されています。

<http://developer.android.com/intl/ja/training/volley/requestqueue.html>


CC BY-SA 3.0
2015-01-30T10:05:04.923
5621
2015-01-30T10:05:04.923
845
5620
answer


@fkm
の回答のリンク先（[公式ドキュメント](http://developer.android.com/training/volley/requestqueue.html#singleton)）や
[StackOverFlow（本家）](https://stackoverflow.com/questions/17336434/instantiating-
core-volley-objects/17336630#17336630) にもありますが、 **Volley の RequestQueue は
AppliationContext のSingleton パターンで使う** ように設計されています。

なので、Application クラスを拡張して、RequestQueue をインスタンス化して保持し、そのインスタンスを他クラスからアクセスするための
getter を定義しておきます。

ちなみに、公式ドキュメントはサンプルコードが編集で乱れて1行目目が欠落しているようですが：

[code]

    public class MySingleton extends Application {
        private static MySingleton mInstance;
        private RequestQueue mRequestQueue;
        private ImageLoader mImageLoader;
        private static Context mCtx;
    
        private MySingleton(Context context) {
            mCtx = context;
    
        //（……以下略）
    
    }
    
[/code]

というのが正しいはずです。

このように、Application の拡張クラスを用意して、あとは、Fragment であれ、他のどのクラスからであっても、MySingleton クラスの
static メソッドである、 **MySingleton.getInstance()** を呼べば ok
です。引数には、ApplicationContext を渡します。ActivityContext を渡してはいけません。

[code]

    RequestQueue queue = MySingleton.getInstance(getActivity().getApplicationContext()).
        getRequestQueue();
    
[/code]

つまり、Bundle でオブジェクトを渡すというのは、Activity から Fragment
という横の関係でオブジェクトを渡す場合のイメージですが、Volley の RequestQueue オブジェクトの場合は、Application
という上位のクラスから各 Activity や Fragment が直接 get して使うような形でイメージすればいいと思います。


CC BY-SA 3.0
2015-01-30T11:53:49.237
5625
2015-01-30T13:10:54.240
2017-05-23T12:38:55.250
-1
7290
5620
answer


@fkm さんおよび、 @hata さんの回答には認識違いがあるので、その点を正しておきます。

公式ドキュメントの記述は真逆です。 **`Application`クラスを継承して持たせない方が良い** と書いてあるのです。

  * `Application`自体が、アプリケーションのライフサイクルを通じて唯一存在することが保証されているクラスなので、シングルトン化する必要、特に`static`変数に保持する必要性が全くありません。`getInstance()`メソッドがなくとも、`Activity`であれば`getApplication()`、`context`を取得できる場所ならば`getApplicationContext()`を、拡張したアプリケーションクラスにキャストすることで取得できます。
  * `Application`クラスで初期化するのに、明示的に`getApplicationContext()`を利用する必要性が皆無です（`Application`の`this`＝`getApplicationContext()`なのですから）。

## 原文と私訳

> The recommended approach is to implement a singleton class that encapsulates
> RequestQueue and other Volley functionality. Another approach is to subclass
> Application and set up the RequestQueue in Application.onCreate(). But this
> approach is discouraged; a static singleton can provide the same
> functionality in a more modular way.

`RequestQueue`および他の`Volley`の機能をカプセル化したシングルトンクラスを実装するアプローチが推奨される。他のアプローチとしては`Application`をサブクラス化し、`Application.onCreate()`で`RequestQueue`のセットアップを行うものがある。しかしこのアプローチは静的なシングルトンがよりモジュール性のある同等の機能を提供するため、思いとどまらせる。

## 単一のオブジェクトにするべき理由と実装方法

> それともフラグメント側でVolley.newRequestQueue()を書いてしまっても良いのでしょうか｡

これは動作しますが、作成した`Volley`の`RequestQueue`の数だけ通信を試みる（並列リクエスト数を一定に制限するためにキューイングの機構があるのに、キューそのものを複数生成したら意味がありません）ため、通信効率が悪くなるため非推奨です。

`RequestQueue`を単一のインスタンスとする方法について、シングルトンクラスに`Application
Context`を保持させる方法と、カスタム`Application`クラスを利用した方法がありますが、機能的には等価なので、どちらでも問題ありません。先述したとおり、公式ドキュメントではモジュール性の観点からシングルトンクラスを作ることを推奨しています。

いずれにせよ重要なのは、 `Volley.newRequestQueue()`で初期化する`context`は`Application
Context`にすべきということです。`Activity
Context`でも機能しますが、その`Activity`が破棄される度に`RequestQueue`が再生成されてしまうためこれも効率の面から微妙です。

アプリケーションの寿命と`RequestQueue`の寿命を同じにすることが望ましいとされています。


CC BY-SA 3.0
2015-01-31T12:21:49.700
5665
2015-01-31T12:26:52.563
2015-01-31T12:26:52.563
5337
5337
5620
answer