ネットワーク通信フレームワーク-Volleyソース分析(1)

6957 ワード

Volleyホームページ:https://android.googlesource.com/platform/frameworks/volley
VolleyはGoogle IO 2013の講演で推薦されたネット通信フレームワークで、主な機能は以下の通りである.
  • JSON、画像等の非同期ダウンロード
  • ネットワークリクエストのソート
  • ネットワーク要求の優先度処理
  • キャッシュ
  • マルチレベルキャンセル要求
  • Activityライフサイクルと連動(Activity終了時にすべてのネットワークリクエストを同時にキャンセル)
  • 画像リクエストに対しては、AsyncTaskレベル制でHttpUrlConnectionを使用してサーバからダウンロードする必要がある場合があり、画面が回転したり、キャッシュメカニズムが欠けたりして、ネットワークからデータを複数回ダウンロードしたりして、不要なネットワークリクエストをもたらす場合があります.これらの問題はVolleyで便利に解決されます.
    Volleyの使い方については、ブログをお勧めします.http://blog.csdn.net/t12x3456/article/details/9221611ああ、これからソースコードを分析して説明します.もし間違ったところがあれば、大牛さんの改善を歓迎します.
    まず、最も簡単なgetリクエストを例に展開します.
    mQueue = Volley.newRequestQueue(getApplicationContext());
    mQueue.add(new JsonObjectRequest(Method.GET, url, null,
                new Listener() {
                    @Override
                    public void onResponse(JSONObject response) {
                        Log.d(TAG, "response : " + response.toString());
                      }
                }, null));
    mQueue.start();

    この例は比較的簡単で,ネットワークからJsonリクエストを取得することである.
    関連するクラスは次のとおりです.
  • Volleyデフォルトのワークプールインスタンス
  • を作成
  • RequestQueueスケジューラスレッドプールを持つリクエストスケジューリングキュー
  • 1.Volley
    public static RequestQueue newRequestQueue(Context context) {
            return newRequestQueue(context, null);
        }
        public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
            File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
            String userAgent = "volley/0";
            try {
                String packageName = context.getPackageName();
                PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
                userAgent = packageName + "/" + info.versionCode;//               ,         
            } catch (NameNotFoundException e) {
            }
            if (stack == null) {//  sdk<9,HttpUrlConnection    ,   sdk>=9,   HurlStack(  HttpURLConnection),    HttpClientStack(  HttpClient)
                if (Build.VERSION.SDK_INT >= 9) {
                    stack = new HurlStack();
                } else {
                    // Prior to Gingerbread, HttpUrlConnection was unreliable.
                    // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
                    stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
                }
            }
            Network network = new BasicNetwork(stack);//    Volley         
            RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);//                     
            queue.start();//        
            return queue;
        }
    

    2.RequestQueue 
    //         
        public void start() {
            stop();  // Make sure any currently running dispatchers are stopped.
            // Create the cache dispatcher and start it.
            mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery);
            mCacheDispatcher.start();
    
            // Create network dispatchers (and corresponding threads) up to the pool size.
            for (int i = 0; i < mDispatchers.length; i++) {
                NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork,
                        mCache, mDelivery);
                mDispatchers[i] = networkDispatcher;
                networkDispatcher.start();
            }
        }
    
    //          
    public void stop() {
            if (mCacheDispatcher != null) {
                mCacheDispatcher.quit();
            }
            for (int i = 0; i < mDispatchers.length; i++) {
                if (mDispatchers[i] != null) {
                    mDispatchers[i].quit();
                }
            }
        }
    
    //             
    public Request add(Request request) {
            // Tag the request as belonging to this queue and add it to the set of current requests.
            request.setRequestQueue(this);
            synchronized (mCurrentRequests) {
                mCurrentRequests.add(request);//            
            }
    
            // Process requests in the order they are added.
            request.setSequence(getSequenceNumber());//    
            request.addMarker("add-to-queue");
    
            // If the request is uncacheable, skip the cache queue and go straight to the network.
            //        ,   ,        ,             ,      
            if (!request.shouldCache()) {
                mNetworkQueue.add(request);
                return request;
            }
    
            // Insert request into stage if there's already a request with the same cache key in flight.
            synchronized (mWaitingRequests) {
                String cacheKey = request.getCacheKey();//    Key ,       url
                if (mWaitingRequests.containsKey(cacheKey)) {//           Key ,      ,           
                    // There is already a request in flight. Queue up.
                    Queue<Request> stagedRequests = mWaitingRequests.get(cacheKey);
                    if (stagedRequests == null) {
                        stagedRequests = new LinkedList<Request>();
                    }
                    stagedRequests.add(request);
                    mWaitingRequests.put(cacheKey, stagedRequests);
                    if (VolleyLog.DEBUG) {
                        VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", cacheKey);
                    }
                } else {//  , null       ,             
                    // Insert 'null' queue for this cacheKey, indicating there is now a request in
                    // flight.
                    mWaitingRequests.put(cacheKey, null);
                    mCacheQueue.add(request);
                }
                return request;
            }
        }
    
     //     
        void finish(Request request) {
            // Remove from the set of requests currently being processed.
            synchronized (mCurrentRequests) {
                mCurrentRequests.remove(request);//             
            }
    
            if (request.shouldCache()) {//      ,         
                synchronized (mWaitingRequests) {
                    String cacheKey = request.getCacheKey();
                    Queue<Request> waitingRequests = mWaitingRequests.remove(cacheKey);
                    if (waitingRequests != null) {
                        if (VolleyLog.DEBUG) {
                            VolleyLog.v("Releasing %d waiting requests for cacheKey=%s.",
                                    waitingRequests.size(), cacheKey);
                        }
                        // Process all queued up requests. They won't be considered as in flight, but
                        // that's not a problem as the cache has been primed by 'request'.
                        mCacheQueue.addAll(waitingRequests);//                  
                    }
                }
            }
        }
    

    Volleyソースのダウンロード:http://download.csdn.net/detail/jhg19900321/7049517