From 1a89ae4cdcf8d467e5d081234ec66a097045f772 Mon Sep 17 00:00:00 2001 From: Katie McCormick Date: Tue, 18 Mar 2014 17:13:50 -0700 Subject: Doc update: new Volley class Change-Id: Ife3a9a64439e07aaaf92a22adc6d1678138caf7d --- "\\" | 19 + docs/html/images/training/volley-request.png | Bin 0 -> 61812 bytes .../html/training/basics/network-ops/connecting.jd | 1 + docs/html/training/basics/network-ops/index.jd | 9 + docs/html/training/training_toc.cs | 29 + docs/html/training/volley/index.jd | 133 ++ docs/html/training/volley/request-custom.jd | 163 ++ docs/html/training/volley/request.jd | 281 +++ docs/html/training/volley/requestqueue.jd | 204 ++ docs/html/training/volley/simple.jd | 169 ++ .../training/volley/volley-request.graffle | 2259 ++++++++++++++++++++ 11 files changed, 3267 insertions(+) create mode 100644 "\\" create mode 100644 docs/html/images/training/volley-request.png create mode 100644 docs/html/training/volley/index.jd create mode 100644 docs/html/training/volley/request-custom.jd create mode 100644 docs/html/training/volley/request.jd create mode 100644 docs/html/training/volley/requestqueue.jd create mode 100644 docs/html/training/volley/simple.jd create mode 100644 docs/image_sources/training/volley/volley-request.graffle diff --git "a/\\" "b/\\" new file mode 100644 index 0000000..1d25d33 --- /dev/null +++ "b/\\" @@ -0,0 +1,19 @@ +Doc update: new Volley class + +Change-Id: Ife3a9a64439e07aaaf92a22adc6d1678138caf7d + +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit. +# On branch volley +# Changes to be committed: +# new file: docs/html/images/training/volley-request.png +# modified: docs/html/training/basics/network-ops/connecting.jd +# modified: docs/html/training/basics/network-ops/index.jd +# modified: docs/html/training/training_toc.cs +# new file: docs/html/training/volley/index.jd +# new file: docs/html/training/volley/request-custom.jd +# new file: docs/html/training/volley/request.jd +# new file: docs/html/training/volley/requestqueue.jd +# new file: docs/html/training/volley/setup.jd +# new file: docs/html/training/volley/simple.jd +# diff --git a/docs/html/images/training/volley-request.png b/docs/html/images/training/volley-request.png new file mode 100644 index 0000000..85f0681 Binary files /dev/null and b/docs/html/images/training/volley-request.png differ diff --git a/docs/html/training/basics/network-ops/connecting.jd b/docs/html/training/basics/network-ops/connecting.jd index 50a9e1b..1452ded 100644 --- a/docs/html/training/basics/network-ops/connecting.jd +++ b/docs/html/training/basics/network-ops/connecting.jd @@ -25,6 +25,7 @@ next.link=managing.html

You should also read

@@ -51,6 +52,14 @@ as a source of reusable code for your own application.

fundamental building blocks for creating Android applications that download content and parse data efficiently, while minimizing network traffic.

+

Note: See the class Transmitting Network Data Using Volley +for information on Volley, an HTTP library that makes networking for Android apps +easier and faster. Volley is available through the open +AOSP +repository. Volley may be able to help you streamline and improve the performance +of your app's network operations.

+

Lessons

diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs index 0616b62..c5dc3c5 100644 --- a/docs/html/training/training_toc.cs +++ b/docs/html/training/training_toc.cs @@ -609,6 +609,35 @@ include the action bar on devices running Android 2.1 or higher." + diff --git a/docs/html/training/volley/index.jd b/docs/html/training/volley/index.jd new file mode 100644 index 0000000..ba5b09f --- /dev/null +++ b/docs/html/training/volley/index.jd @@ -0,0 +1,133 @@ +page.title=Transmitting Network Data Using Volley +page.tags="" + +trainingnavtop=true +startpage=true + + +@jd:body + + + +
+
+ + + +

Dependencies and prerequisites

+ +
    +
  • Android 1.6 (API Level 4) or higher
  • +
+ +

You should also see

+ + +
+
+ + +
+

Video

+

Volley: Easy, Fast Networking for Android

+
+
+ + +

Volley is an HTTP library that makes networking for Android apps easier and most importantly, +faster. Volley is available through the open +AOSP repository.

+ +

Volley offers the following benefits:

+ + + +

Volley excels at RPC-type operations used to populate a UI, such as fetching a page of +search results as structured data. It integrates easily with any protocol and comes out of +the box with support for raw strings, images, and JSON. By providing built-in support for +the features you need, Volley frees you from writing boilerplate code and allows you to +concentrate on the logic that is specific to your app.

+

Volley is not suitable for large download or streaming operations, since Volley holds +all responses in memory during parsing. For large download operations, consider using an +alternative like {@link android.app.DownloadManager}.

+ +

The core Volley library is developed in the open +AOSP +repository at {@code frameworks/volley} and contains the main request dispatch pipeline +as well as a set of commonly applicable utilities, available in the Volley "toolbox." The +easiest way to add Volley to your project is to clone the Volley repository and set it as +a library project:

+ +
    +
  1. Git clone the repository by typing the following at the command line: + +
    +git clone https://android.googlesource.com/platform/frameworks/volley
    +
    +
  2. + +
  3. Import the downloaded source into your app project as an Android library project +(as described in +Managing Projects from Eclipse with ADT, if you're using Eclipse) or make a +.jar file.
  4. +
+ +

Lessons

+ +
+
+ Sending a Simple Request +
+
+ Learn how to send a simple request using the default behaviors of Volley, and how + to cancel a request. + +
+
+ Setting Up a RequestQueue +
+
+ Learn how to set up a {@code RequestQueue}, and how to implement a singleton + pattern to create a {@code RequestQueue} that lasts the lifetime of your app. +
+
+ Making a Standard Request +
+
+ Learn how to send a request using one of Volley's out-of-the-box request types + (raw strings, images, and JSON). +
+
+ Implementing a Custom Request +
+
+ Learn how to implement a custom request. +
+ +
diff --git a/docs/html/training/volley/request-custom.jd b/docs/html/training/volley/request-custom.jd new file mode 100644 index 0000000..7b669b9 --- /dev/null +++ b/docs/html/training/volley/request-custom.jd @@ -0,0 +1,163 @@ +page.title=Implementing a Custom Request + +trainingnavtop=true + +@jd:body + +
+
+ + +

This lesson teaches you to

+
    +
  1. Write a Custom Request
  2. +
+ +
+
+ + +
+

Video

+

Volley: Easy, Fast Networking for Android

+
+
+ +

This lesson describes how to implement your own custom request types, for types that +don't have out-of-the-box Volley support.

+ +

Write a Custom Request

+ +Most requests have ready-to-use implementations in the toolbox; if your response is a string, +image, or JSON, you probably won't need to implement a custom {@code Request}.

+ +

For cases where you do need to implement a custom request, this is all you need +to do:

+ + + +

parseNetworkResponse

+ +

A {@code Response} encapsulates a parsed response for delivery, for a given type +(such as string, image, or JSON). Here is a sample implementation of +{@code parseNetworkResponse()}:

+ +
+@Override
+protected Response<T> parseNetworkResponse(
+        NetworkResponse response) {
+    try {
+        String json = new String(response.data,
+        HttpHeaderParser.parseCharset(response.headers));
+    return Response.success(gson.fromJson(json, clazz),
+    HttpHeaderParser.parseCacheHeaders(response));
+    }
+    // handle errors
+...
+}
+
+ +

Note the following:

+ + + +

If your protocol has non-standard cache semantics, you can build a {@code Cache.Entry} +yourself, but most requests are fine with something like this: +

+
return Response.success(myDecodedObject,
+        HttpHeaderParser.parseCacheHeaders(response));
+

+Volley calls {@code parseNetworkResponse()} from a worker thread. This ensures that +expensive parsing operations, such as decoding a JPEG into a Bitmap, don't block the UI +thread.

+ +

deliverResponse

+ +

Volley calls you back on the main thread with the object you returned in +{@code parseNetworkResponse()}. Most requests invoke a callback interface here, +for example: +

+ +
+protected void deliverResponse(T response) {
+        listener.onResponse(response);
+
+ +

Example: GsonRequest

+ +

Gson is a library for converting +Java objects to and from JSON using reflection. You can define Java objects that have the +same names as their corresponding JSON keys, pass Gson the class object, and Gson will fill +in the fields for you. Here's a complete implementation of a Volley request that uses +Gson for parsing:

+ +
+public class GsonRequest<T> extends Request<T> {
+    private final Gson gson = new Gson();
+    private final Class<T> clazz;
+    private final Map<String, String> headers;
+    private final Listener<T> listener;
+
+    /**
+     * Make a GET request and return a parsed object from JSON.
+     *
+     * @param url URL of the request to make
+     * @param clazz Relevant class object, for Gson's reflection
+     * @param headers Map of request headers
+     */
+    public GsonRequest(String url, Class<T> clazz, Map<String, String> headers,
+            Listener<T> listener, ErrorListener errorListener) {
+        super(Method.GET, url, errorListener);
+        this.clazz = clazz;
+        this.headers = headers;
+        this.listener = listener;
+    }
+
+    @Override
+    public Map<String, String> getHeaders() throws AuthFailureError {
+        return headers != null ? headers : super.getHeaders();
+    }
+
+    @Override
+    protected void deliverResponse(T response) {
+        listener.onResponse(response);
+    }
+
+    @Override
+    protected Response<T> parseNetworkResponse(NetworkResponse response) {
+        try {
+            String json = new String(
+                    response.data,
+                    HttpHeaderParser.parseCharset(response.headers));
+            return Response.success(
+                    gson.fromJson(json, clazz),
+                    HttpHeaderParser.parseCacheHeaders(response));
+        } catch (UnsupportedEncodingException e) {
+            return Response.error(new ParseError(e));
+        } catch (JsonSyntaxException e) {
+            return Response.error(new ParseError(e));
+        }
+    }
+}
+
+ +

Volley provides ready-to-use {@code JsonArrayRequest} and {@code JsonArrayObject} classes +if you prefer to take that approach. See +Using Standard Request Types for more information.

diff --git a/docs/html/training/volley/request.jd b/docs/html/training/volley/request.jd new file mode 100644 index 0000000..d8ccab2 --- /dev/null +++ b/docs/html/training/volley/request.jd @@ -0,0 +1,281 @@ +page.title=Making a Standard Request + +trainingnavtop=true + +@jd:body + +
+
+ + +

This lesson teaches you to

+
    +
  1. Request an Image
  2. +
  3. Request JSON
  4. +
+ +
+
+ + +
+

Video

+

Volley: Easy, Fast Networking for Android

+
+
+ +

+This lesson describes how to use the common request types that Volley supports:

+ + + +

If your expected response is one of these types, you probably won't have to implement a +custom request. This lesson describes how to use these standard request types. For +information on how to implement your own custom request, see +Implementing a Custom Request.

+ + +

Request an Image

+ +

Volley offers the following classes for requesting images. These classes layer on top +of each other to offer different levels of support for processing images:

+ + + +

Use ImageRequest

+ +

Here is an example of using {@code ImageRequest}. It retrieves the image specified by +the URL and displays it in the app. Note that this snippet interacts with the +{@code RequestQueue} through a singleton class (see Setting Up a RequestQueue for more discussion of +this topic):

+ +
+ImageView mImageView;
+String url = "http://i.imgur.com/7spzG.png";
+mImageView = (ImageView) findViewById(R.id.myImage);
+...
+
+// Retrieves an image specified by the URL, displays it in the UI.
+ImageRequest request = new ImageRequest(url,
+    new Response.Listener() {
+        @Override
+        public void onResponse(Bitmap bitmap) {
+            mImageView.setImageBitmap(bitmap);
+        }
+    }, 0, 0, null,
+    new Response.ErrorListener() {
+        public void onErrorResponse(VolleyError error) {
+            mImageView.setImageResource(R.drawable.image_load_error);
+        }
+    });
+// Access the RequestQueue through your singleton class.
+MySingleton.getInstance(this).addToRequestQueue(request);
+ + +

Use ImageLoader and NetworkImageView

+ +

You can use {@code ImageLoader} and {@code NetworkImageView} in concert to efficiently +manage the display of multiple images, such as in a {@link android.widget.ListView}. In your +layout XML file, you use {@code NetworkImageView} in much the same way you would use +{@link android.widget.ImageView}, for example:

+ +
<com.android.volley.toolbox.NetworkImageView
+        android:id="@+id/networkImageView"
+        android:layout_width="150dp"
+        android:layout_height="170dp"
+        android:layout_centerHorizontal="true" />
+ +

You can use {@code ImageLoader} by itself to display an image, for example:

+ +
+ImageLoader mImageLoader;
+ImageView mImageView;
+// The URL for the image that is being loaded.
+private static final String IMAGE_URL =
+    "http://developer.android.com/images/training/system-ui.png";
+...
+mImageView = (ImageView) findViewById(R.id.regularImageView);
+
+// Get the ImageLoader through your singleton class.
+mImageLoader = MySingleton.getInstance(this).getImageLoader();
+mImageLoader.get(IMAGE_URL, ImageLoader.getImageListener(mImageView,
+         R.drawable.def_image, R.drawable.err_image));
+
+ +

However, {@code NetworkImageView} can do this for you if all you're doing is populating +an {@link android.widget.ImageView}. For example:

+ +
+ImageLoader mImageLoader;
+NetworkImageView mNetworkImageView;
+private static final String IMAGE_URL =
+    "http://developer.android.com/images/training/system-ui.png";
+...
+
+// Get the NetworkImageView that will display the image.
+mNetworkImageView = (NetworkImageView) findViewById(R.id.networkImageView);
+
+// Get the ImageLoader through your singleton class.
+mImageLoader = MySingleton.getInstance(this).getImageLoader();
+
+// Set the URL of the image that should be loaded into this view, and
+// specify the ImageLoader that will be used to make the request.
+mNetworkImageView.setImageUrl(IMAGE_URL, mImageLoader);
+
+ +

The above snippets access the {@code RequestQueue} and the {@code ImageLoader} +through a singleton class, as described in +Setting Up a RequestQueue. This approach ensures that your app creates single instances of +these classes that last the lifetime of your app. The reason that this is important for +{@code ImageLoader} (the helper class that handles loading and caching images) is that +the main function of the in-memory cache is to allow for flickerless rotation. Using a +singleton pattern allows the bitmap cache to outlive the activity. If instead you create the +{@code ImageLoader} in an activity, the {@code ImageLoader} would be recreated along with +the activity every time the user rotates the device. This would cause flickering.

+ +

Example LRU cache

+ +

The Volley toolbox provides a standard cache implementation via the +{@code DiskBasedCache} class. This class caches files directly onto the hard disk in the +specified directory. But to use {@code ImageLoader}, you should provide a custom +in-memory LRU bitmap cache that implements the {@code ImageLoader.ImageCache} interface. +You may want to set up your cache as a singleton; for more discussion of this topic, see + +Setting Up a RequestQueue.

+ +

Here is a sample implementation for an in-memory {@code LruBitmapCache} class. +It extends the {@link android.support.v4.util.LruCache} class and implements the +{@code ImageLoader.ImageCache} interface:

+ +
+import android.graphics.Bitmap;
+import android.support.v4.util.LruCache;
+import android.util.DisplayMetrics;
+import com.android.volley.toolbox.ImageLoader.ImageCache;
+
+public class LruBitmapCache extends LruCache<String, Bitmap>
+        implements ImageCache {
+
+    public LruBitmapCache(int maxSize) {
+        super(maxSize);
+    }
+
+    public LruBitmapCache(Context ctx) {
+        this(getCacheSize(ctx));
+    }
+
+    @Override
+    protected int sizeOf(String key, Bitmap value) {
+        return value.getRowBytes() * value.getHeight();
+    }
+
+    @Override
+    public Bitmap getBitmap(String url) {
+        return get(url);
+    }
+
+    @Override
+    public void putBitmap(String url, Bitmap bitmap) {
+        put(url, bitmap);
+    }
+
+    // Returns a cache size equal to approximately three screens worth of images.
+    public static int getCacheSize(Context ctx) {
+        final DisplayMetrics displayMetrics = ctx.getResources().
+                getDisplayMetrics();
+        final int screenWidth = displayMetrics.widthPixels;
+        final int screenHeight = displayMetrics.heightPixels;
+        // 4 bytes per pixel
+        final int screenBytes = screenWidth * screenHeight * 4;
+
+        return screenBytes * 3;
+    }
+}
+
+ +

Here is an example of how to instantiate an {@code ImageLoader} to use this +cache:

+ +
+RequestQueue mRequestQueue; // assume this exists.
+ImageLoader mImageLoader = new ImageLoader(mRequestQueue, new LruBitmapCache(
+            LruBitmapCache.getCacheSize()));
+
+ + +

Request JSON

+ +

Volley provides the following classes for JSON requests:

+ + + +

Both classes are based on the common base class {@code JsonRequest}. You use them +following the same basic pattern you use for other types of requests. For example, this +snippet fetches a JSON feed and displays it as text in the UI:

+ +
+TextView mTxtDisplay;
+ImageView mImageView;
+mTxtDisplay = (TextView) findViewById(R.id.txtDisplay);
+String url = "http://my-json-feed";
+
+JsonObjectRequest jsObjRequest = new JsonObjectRequest
+        (Request.Method.GET, url, null, new Response.Listener() {
+
+    @Override
+    public void onResponse(JSONObject response) {
+        mTxtDisplay.setText("Response: " + response.toString());
+    }
+}, new Response.ErrorListener() {
+
+    @Override
+    public void onErrorResponse(VolleyError error) {
+        // TODO Auto-generated method stub
+
+    }
+});
+
+// Access the RequestQueue through your singleton class.
+MySingleton.getInstance(this).addToRequestQueue(jsObjRequest);
+
+ +For an example of implementing a custom JSON request based on +Gson, see the next lesson, +Implementing a Custom Request. diff --git a/docs/html/training/volley/requestqueue.jd b/docs/html/training/volley/requestqueue.jd new file mode 100644 index 0000000..6858d91 --- /dev/null +++ b/docs/html/training/volley/requestqueue.jd @@ -0,0 +1,204 @@ +page.title=Setting Up a RequestQueue + +trainingnavtop=true + +@jd:body + +
+
+ + +

This lesson teaches you to

+
    +
  1. Set Up a Network and Cache
  2. +
  3. Use a Singleton Pattern
  4. +
+ +
+
+ + +
+

Video

+

Volley: Easy, Fast Networking for Android

+
+
+ + +

The previous lesson showed you how to use the convenience method +Volley.newRequestQueue to set up a {@code RequestQueue}, taking advantage of +Volley's default behaviors. This lesson walks you through the explicit steps of creating a +{@code RequestQueue}, to allow you to supply your own custom behavior.

+ +

This lesson also describes the recommended practice of creating a {@code RequestQueue} +as a singleton, which makes the {@code RequestQueue} last the lifetime of your app.

+ +

Set Up a Network and Cache

+ +

A {@code RequestQueue} needs two things to do its job: a network to perform transport +of the requests, and a cache to handle caching. There are standard implementations of these +available in the Volley toolbox: {@code DiskBasedCache} provides a one-file-per-response +cache with an in-memory index, and {@code BasicNetwork} provides a network transport based +on your choice of {@link android.net.http.AndroidHttpClient} or {@link java.net.HttpURLConnection}.

+ +

{@code BasicNetwork} is Volley's default network implementation. A {@code BasicNetwork} +must be initialized with the HTTP client your app is using to connect to the network. +Typically this is {@link android.net.http.AndroidHttpClient} or +{@link java.net.HttpURLConnection}:

+ +

To create an app that runs on all versions of Android, you can check the version of +Android the device is running and choose the appropriate HTTP client, for example:

+ +
+HttpStack stack;
+...
+// If the device is running a version >= Gingerbread...
+if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
+    // ...use HttpURLConnection for stack.
+} else {
+    // ...use AndroidHttpClient for stack.
+}
+Network network = new BasicNetwork(stack);
+
+ +

This snippet shows you the steps involved in setting up a +{@code RequestQueue}:

+ +
+RequestQueue mRequestQueue;
+
+// 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.
+mRequestQueue = new RequestQueue(cache, network);
+
+// Start the queue
+mRequestQueue.start();
+
+String url ="http://www.myurl.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.
+mRequestQueue.add(stringRequest);
+...
+
+ +

If you just need to make a one-time request and don't want to leave the thread pool +around, you can create the {@code RequestQueue} wherever you need it and call {@code stop()} on the +{@code RequestQueue} once your response or error has come back, using the +{@code Volley.newRequestQueue()} method described in Sending a Simple +Request. But the more common use case is to create the {@code RequestQueue} as a +singleton to keep it running for the lifetime of your app, as described in the next section.

+ + +

Use a Singleton Pattern

+ +

If your application makes constant use of the network, it's probably most efficient to +set up a single instance of {@code RequestQueue} that will last the lifetime of your app. +You can achieve this in various ways. The recommended approach is to implement a singleton +class that encapsulates {@code RequestQueue} and other Volley +functionality. Another approach is to subclass {@link android.app.Application} and set up the +{@code RequestQueue} in {@link android.app.Application#onCreate Application.onCreate()}. +But this approach is +discouraged; a static singleton can provide the same functionality in a more modular +way.

+ +

A key concept is that the {@code RequestQueue} must be instantiated with the +{@link android.app.Application} context, not an {@link android.app.Activity} context. This +ensures that the {@code RequestQueue} will last for the lifetime of your app, instead of +being recreated every time the activity is recreated (for example, when the user +rotates the device). + +

Here is an example of a singleton class that provides {@code RequestQueue} and +{@code ImageLoader} functionality:

+ +
private static MySingleton mInstance;
+    private RequestQueue mRequestQueue;
+    private ImageLoader mImageLoader;
+    private static Context mCtx;
+
+    private MySingleton(Context context) {
+        mCtx = context;
+        mRequestQueue = getRequestQueue();
+
+        mImageLoader = new ImageLoader(mRequestQueue,
+                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 (mInstance == null) {
+            mInstance = new MySingleton(context);
+        }
+        return mInstance;
+    }
+
+    public RequestQueue getRequestQueue() {
+        if (mRequestQueue == null) {
+            // getApplicationContext() is key, it keeps you from leaking the
+            // Activity or BroadcastReceiver if someone passes one in.
+            mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
+        }
+        return mRequestQueue;
+    }
+
+    public <T> void addToRequestQueue(Request<T> req) {
+        getRequestQueue().add(req);
+    }
+
+    public ImageLoader getImageLoader() {
+        return mImageLoader;
+    }
+}
+ +

Here are some examples of performing {@code RequestQueue} operations using the singleton +class:

+ +
+// 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);
+
diff --git a/docs/html/training/volley/simple.jd b/docs/html/training/volley/simple.jd new file mode 100644 index 0000000..942c57f --- /dev/null +++ b/docs/html/training/volley/simple.jd @@ -0,0 +1,169 @@ +page.title=Sending a Simple Request + +trainingnavtop=true + +@jd:body + +
+
+ + +

This lesson teaches you to

+
    +
  1. Add the INTERNET Permission
  2. +
  3. Use newRequestQueue
  4. +
  5. Send a Request
  6. +
  7. Cancel a Request
  8. +
+ +
+
+ + +
+

Video

+

Volley: Easy, Fast Networking for Android

+
+
+ +

At a high level, you use Volley by creating a {@code RequestQueue} and passing it +{@code Request} objects. The {@code RequestQueue} manages worker threads for running the +network operations, reading from and writing to the cache, and parsing responses. Requests +do the parsing of raw responses and Volley takes care of dispatching the parsed response +back to the main thread for delivery.

+ +

This lesson describes how to send a request using the Volley.newRequestQueue +convenience method, which sets up a {@code RequestQueue} for you. +See the next lesson, +Setting Up a RequestQueue, for information on how to set +up a {@code RequestQueue} yourself.

+ +

This lesson also describes how to add a request to a {@code RequestQueue} and cancel a +request.

+ +

Add the INTERNET Permission

+ +

To use Volley, you must add the +{@link android.Manifest.permission#INTERNET android.permission.INTERNET} permission +to your app's manifest. Without this, your app won't be able to connect to the network.

+ + +

Use newRequestQueue

+ +

Volley provides a convenience method Volley.newRequestQueue that sets up a +{@code RequestQueue} for you, using default values, and starts the queue. For example:

+ +
+final TextView mTextView = (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() {
+    @Override
+    public void onResponse(String response) {
+        // Display the first 500 characters of the response string.
+        mTextView.setText("Response is: "+ response.substring(0,500));
+    }
+}, new Response.ErrorListener() {
+    @Override
+    public void onErrorResponse(VolleyError error) {
+        mTextView.setText("That didn't work!");
+    }
+});
+// Add the request to the RequestQueue.
+queue.add(stringRequest);
+
+ +

Volley always delivers parsed responses on the main thread. Running on the main thread +is convenient for populating UI controls with received data, as you can freely modify UI +controls directly from your response handler, but it's especially critical to many of the +important semantics provided by the library, particularly related to canceling requests. +

+ +

See Setting Up a RequestQueue for a +description of how to set up a {@code RequestQueue} yourself, instead of using the +Volley.newRequestQueue convenience method.

+ +

Send a Request

+ +

To send a request, you simply construct one and add it to the {@code RequestQueue} with +{@code add()}, as shown above. Once you add the request it moves through the pipeline, +gets serviced, and has its raw response parsed and delivered.

+ +

When you call {@code add()}, Volley runs one cache processing thread and a pool of +network dispatch threads. When you add a request to the queue, it is picked up by the cache +thread and triaged: if the request can be serviced from cache, the cached response is +parsed on the cache thread and the parsed response is delivered on the main thread. If the +request cannot be serviced from cache, it is placed on the network queue. The first +available network thread takes the request from the queue, performs the HTTP transaction, +parsse the response on the worker thread, writes the response to cache, and posts the parsed +response back to the main thread for delivery.

+ +

Note that expensive operations like blocking I/O and parsing/decoding are done on worker +threads. You can add a request from any thread, but responses are always delivered on the +main thread.

+ +

Figure 1 illustrates the life of a request:

+ + system bars +

Figure 1. Life of a request.

+ + +

Cancel a Request

+ +

To cancel a request, call {@code cancel()} on your {@code Request} object. Once cancelled, +Volley guarantees that your response handler will never be called. What this means in +practice is that you can cancel all of your pending requests in your activity's +{@link android.app.Activity#onStop onStop()} method and you don't have to litter your +response handlers with checks for {@code getActivity() == null}, +whether {@code onSaveInstanceState()} has been called already, or other defensive +boilerplate.

+ +

To take advantage of this behavior, you would typically have to +track all in-flight requests in order to be able to cancel them at the +appropriate time. There is an easier way: you can associate a tag object with each +request. You can then use this tag to provide a scope of requests to cancel. For +example, you can tag all of your requests with the {@link android.app.Activity} they +are being made on behalf of, and call {@code requestQueue.cancelAll(this)} from +{@link android.app.Activity#onStop onStop()}. +Similarly, you could tag all thumbnail image requests in a +{@link android.support.v4.view.ViewPager} tab with their respective tabs and cancel on swipe +to make sure that the new tab isn't being held up by requests from another one.

+ +

Here is an example that uses a string value for the tag:

+ +
    +
  1. Define your tag and add it to your requests. +
    +public static final String TAG = "MyTag";
    +StringRequest stringRequest; // Assume this exists.
    +RequestQueue mRequestQueue;  // Assume this exists.
    +
    +// Set the tag on the request.
    +stringRequest.setTag(TAG);
    +
    +// Add the request to the RequestQueue.
    +mRequestQueue.add(stringRequest);
    +
  2. + +
  3. In your activity's {@link android.app.Activity#onStop onStop()} method, cancel all requests that have this tag. +
    +@Override
    +protected void onStop () {
    +    super.onStop();
    +    if (mRequestQueue != null) {
    +        mRequestQueue.cancelAll(TAG);
    +    }
    +}
    +
+ +

Take care when canceling requests. If you are depending on your response handler to +advance a state or kick off another process, you need to account for this. Again, the +response handler will not be called. +

diff --git a/docs/image_sources/training/volley/volley-request.graffle b/docs/image_sources/training/volley/volley-request.graffle new file mode 100644 index 0000000..1d79b3d --- /dev/null +++ b/docs/image_sources/training/volley/volley-request.graffle @@ -0,0 +1,2259 @@ + + + + + ActiveLayerIndex + 0 + ApplicationVersion + + com.omnigroup.OmniGrafflePro + 139.18.0.187838 + + AutoAdjust + + BackgroundGraphic + + Bounds + {{0, 0}, {576, 733}} + Class + SolidGraphic + ID + 2 + Style + + shadow + + Draws + NO + + stroke + + Draws + NO + + + + BaseZoom + 0 + CanvasOrigin + {0, 0} + ColumnAlign + 1 + ColumnSpacing + 36 + CreationDate + 2014-03-24 22:38:51 +0000 + Creator + Katie McCormick + DisplayScale + 1 0/72 in = 1 0/72 in + GraphDocumentVersion + 8 + GraphicsList + + + Bounds + {{68.798424333456921, 309.90064645900816}, {70.999998092651367, 24}} + Class + ShapedGraphic + FitText + Vertical + Flow + Resize + FontInfo + + Color + + b + 0 + g + 0 + r + 0 + + Font + Helvetica + Size + 12 + + ID + 1990 + Rotation + 88.863800048828125 + Shape + Rectangle + Style + + fill + + Draws + NO + + shadow + + Draws + NO + + stroke + + Draws + NO + + + Text + + Align + 0 + Text + {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720 + +\f0\fs24 \cf0 cache miss} + + + + Bounds + {{164.31081962585449, 233}, {59, 24}} + Class + ShapedGraphic + FitText + YES + Flow + Resize + FontInfo + + Color + + b + 0 + g + 0 + r + 0 + + Font + Helvetica + Size + 12 + + ID + 1989 + Shape + Rectangle + Style + + fill + + Draws + NO + + shadow + + Draws + NO + + stroke + + Draws + NO + + + Text + + Align + 0 + Text + {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720 + +\f0\fs24 \cf0 cache hit} + + Wrap + NO + + + Bounds + {{109, 567.5}, {72, 24}} + Class + ShapedGraphic + FitText + YES + Flow + Resize + FontInfo + + Color + + b + 0 + g + 0 + r + 0 + + Font + Helvetica + Size + 12 + + ID + 1987 + Shape + Rectangle + Style + + fill + + Draws + NO + + shadow + + Draws + NO + + stroke + + Draws + NO + + + Text + + Align + 0 + Text + {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720 + +\f0\fs24 \cf0 round-robin} + + Wrap + NO + + + Class + LineGraphic + Head + + ID + 209 + + ID + 1986 + Points + + {362.483096786499, 520.41741752624512} + {439.59458923339844, 165.16970062255859} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + Tail + + ID + 213 + Info + 7 + + + + Class + LineGraphic + Head + + ID + 209 + + ID + 1985 + Points + + {362.483096786499, 461.33483529090881} + {439.59458923339844, 165.16970062255859} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + Tail + + ID + 204 + Info + 7 + + + + Class + LineGraphic + Head + + ID + 209 + + ID + 1984 + Points + + {362.48308152770994, 402.2522608306885} + {439.59458923339844, 165.16970062255859} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + Tail + + ID + 203 + Info + 7 + + + + Class + LineGraphic + Head + + ID + 209 + + ID + 1983 + Points + + {294.65540856933592, 227.99996948242188} + {381.3049268594778, 164.77353614247437} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + Tail + + ID + 210 + Info + 6 + + + + Class + LineGraphic + Head + + ID + 4 + Info + 6 + + ID + 1982 + Points + + {94.216227905273399, 165.16970062255859} + {92.966230102539043, 227.99999237060547} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + Tail + + ID + 157 + Info + 5 + + + + Class + LineGraphic + Head + + ID + 213 + Info + 9 + + ID + 1980 + Points + + {179.26087951660151, 462.43391850741568} + {224.48312730407713, 514.92974541704564} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + Tail + + ID + 1973 + Info + 3 + + + + Class + LineGraphic + Head + + ID + 204 + Info + 8 + + ID + 1979 + Points + + {179.76073189455099, 462.42177007636207} + {224.48312730407716, 461.33483529090881} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + Tail + + ID + 1973 + + + + Class + LineGraphic + Head + + ID + 203 + Info + 8 + + ID + 1978 + Points + + {179.26087951660151, 462.43391850741568} + {224.48311204528804, 402.2522608306885} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + Tail + + ID + 1973 + Info + 3 + + + + Class + LineGraphic + Head + + ID + 1973 + + ID + 1975 + Points + + {92.966230102539043, 286.16969299316406} + {92.966239929199205, 356.41910654608148} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + Tail + + ID + 4 + Info + 5 + + + + Class + LineGraphic + Head + + ID + 210 + Info + 8 + + ID + 1974 + Points + + {150.81081933593748, 257.08484268188477} + {236.81081933593748, 257.08481979370117} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + + + Tail + + ID + 4 + Info + 7 + + + + Bounds + {{391, 540.66744232177734}, {137.99996948242188, 23.499996185302734}} + Class + ShapedGraphic + FontInfo + + Color + + b + 0 + g + 0 + r + 0 + + Font + Roboto-BoldCondensed + Size + 12 + + ID + 214 + Magnets + + {1, 1} + {1, -1} + {-1, -1} + {-1, 1} + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + {-0.5, -0.233518} + {-0.49144199999999999, 0.26006299999999999} + {0.50711799999999996, -0.22408600000000001} + {0.50711799999999996, 0.267179} + {-0.27431, -0.474028} + {0.27977999999999997, -0.47847800000000001} + {0.29393799999999998, 0.54304399999999997} + {-0.28623199999999999, 0.55380399999999996} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.2 + g + 0.733333 + r + 1 + + + shadow + + Color + + a + 0.35 + b + 0.328823 + g + 0.328823 + r + 0.328823 + + Fuzziness + 1.5349206924438477 + ShadowVector + {0, 1} + + stroke + + Color + + b + 0.131021 + g + 0.363196 + r + 0.725948 + + CornerRadius + 2 + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\b\fs24 \cf0 network threads} + VerticalPad + 0 + + + + Bounds + {{224.48312730407713, 508.66741943359375}, {137.99996948242188, 23.499996185302734}} + Class + ShapedGraphic + FontInfo + + Color + + b + 0 + g + 0 + r + 0 + + Font + Roboto-BoldCondensed + Size + 12 + + ID + 213 + Magnets + + {1, 1} + {1, -1} + {-1, -1} + {-1, 1} + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + {-0.5, -0.233518} + {-0.49144199999999999, 0.26006299999999999} + {0.50711799999999996, -0.22408600000000001} + {0.50711799999999996, 0.267179} + {-0.27431, -0.474028} + {0.27977999999999997, -0.47847800000000001} + {0.29393799999999998, 0.54304399999999997} + {-0.28623199999999999, 0.55380399999999996} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.2 + g + 0.733333 + r + 1 + + + shadow + + Color + + a + 0.35 + b + 0.328823 + g + 0.328823 + r + 0.328823 + + Fuzziness + 1.5349206924438477 + ShadowVector + {0, 1} + + stroke + + Color + + b + 0.131021 + g + 0.363196 + r + 0.725948 + + CornerRadius + 2 + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\b\fs24 \cf0 HTTP...} + VerticalPad + 0 + + + + Bounds + {{23.966230102539043, 498}, {137.99998474121094, 58.169700622558594}} + Class + ShapedGraphic + FontInfo + + Color + + b + 0 + g + 0 + r + 0 + + Font + Roboto-BoldCondensed + Size + 12 + + ID + 212 + Magnets + + {1, 1} + {1, -1} + {-1, -1} + {-1, 1} + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + {-0.5, -0.233518} + {-0.49144199999999999, 0.26006299999999999} + {0.50711799999999996, -0.22408600000000001} + {0.50711799999999996, 0.267179} + {-0.27431, -0.474028} + {0.27977999999999997, -0.47847800000000001} + {0.29393799999999998, 0.54304399999999997} + {-0.28623199999999999, 0.55380399999999996} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.2 + g + 0.733333 + r + 1 + + + shadow + + Color + + a + 0.35 + b + 0.328823 + g + 0.328823 + r + 0.328823 + + Fuzziness + 1.5349206924438477 + ShadowVector + {0, 1} + + stroke + + Color + + b + 0.131021 + g + 0.363196 + r + 0.725948 + + CornerRadius + 2 + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\b\fs24 \cf0 Request dequeued by NetworkDispatcher} + VerticalPad + 0 + + + + Bounds + {{23.966245361328106, 432.24999237060547}, {137.99998474121094, 58.169700622558594}} + Class + ShapedGraphic + FontInfo + + Color + + b + 0 + g + 0 + r + 0 + + Font + Roboto-BoldCondensed + Size + 12 + + ID + 211 + Magnets + + {1, 1} + {1, -1} + {-1, -1} + {-1, 1} + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + {-0.5, -0.233518} + {-0.49144199999999999, 0.26006299999999999} + {0.50711799999999996, -0.22408600000000001} + {0.50711799999999996, 0.267179} + {-0.27431, -0.474028} + {0.27977999999999997, -0.47847800000000001} + {0.29393799999999998, 0.54304399999999997} + {-0.28623199999999999, 0.55380399999999996} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.2 + g + 0.733333 + r + 1 + + + shadow + + Color + + a + 0.35 + b + 0.328823 + g + 0.328823 + r + 0.328823 + + Fuzziness + 1.5349206924438477 + ShadowVector + {0, 1} + + stroke + + Color + + b + 0.131021 + g + 0.363196 + r + 0.725948 + + CornerRadius + 2 + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\b\fs24 \cf0 Request dequeued by NetworkDispatcher} + VerticalPad + 0 + + + + Bounds + {{236.81081933593748, 227.99996948242188}, {115.68917846679688, 58.169700622558594}} + Class + ShapedGraphic + FontInfo + + Color + + b + 0 + g + 0 + r + 0 + + Font + Roboto-BoldCondensed + Size + 10 + + ID + 210 + Magnets + + {1, 1} + {1, -1} + {-1, -1} + {-1, 1} + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + {-0.5, -0.233518} + {-0.49144199999999999, 0.26006299999999999} + {0.50711799999999996, -0.22408600000000001} + {0.50711799999999996, 0.267179} + {-0.27431, -0.474028} + {0.27977999999999997, -0.47847800000000001} + {0.29393799999999998, 0.54304399999999997} + {-0.28623199999999999, 0.55380399999999996} + + Shape + Rectangle + Style + + fill + + Color + + b + 0 + g + 0.8 + r + 0.6 + + + shadow + + Color + + a + 0.35 + b + 0.328823 + g + 0.328823 + r + 0.328823 + + Fuzziness + 1.5349206924438477 + ShadowVector + {0, 1} + + stroke + + Color + + b + 0 + g + 0.6 + r + 0.4 + + CornerRadius + 2 + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\b\fs24 \cf0 Request read from cache and parsed} + VerticalPad + 0 + + + + Bounds + {{380.5, 107}, {118.18917846679688, 58.169700622558594}} + Class + ShapedGraphic + FontInfo + + Color + + b + 0 + g + 0 + r + 0 + + Font + Roboto-BoldCondensed + Size + 12 + + ID + 209 + Magnets + + {1, 1} + {1, -1} + {-1, -1} + {-1, 1} + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + {-0.5, -0.233518} + {-0.49144199999999999, 0.26006299999999999} + {0.50711799999999996, -0.22408600000000001} + {0.50711799999999996, 0.267179} + {-0.27431, -0.474028} + {0.27977999999999997, -0.47847800000000001} + {0.29393799999999998, 0.54304399999999997} + {-0.28623199999999999, 0.55380399999999996} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.898039 + g + 0.709804 + r + 0.2 + + + shadow + + Color + + a + 0.35 + b + 0.328823 + g + 0.328823 + r + 0.328823 + + Fuzziness + 1.5349206924438477 + ShadowVector + {0, 1} + + stroke + + Color + + b + 0.93512 + g + 0.472602 + r + 0.333854 + + CornerRadius + 2 + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\b\fs24 \cf0 Parsed response delivered on main thread} + VerticalPad + 0 + + + + Bounds + {{391, 508.66740417480469}, {137.99996948242188, 23.499996185302734}} + Class + ShapedGraphic + FontInfo + + Color + + b + 0 + g + 0 + r + 0 + + Font + Roboto-BoldCondensed + Size + 10 + + ID + 207 + Magnets + + {1, 1} + {1, -1} + {-1, -1} + {-1, 1} + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + {-0.5, -0.233518} + {-0.49144199999999999, 0.26006299999999999} + {0.50711799999999996, -0.22408600000000001} + {0.50711799999999996, 0.267179} + {-0.27431, -0.474028} + {0.27977999999999997, -0.47847800000000001} + {0.29393799999999998, 0.54304399999999997} + {-0.28623199999999999, 0.55380399999999996} + + Shape + Rectangle + Style + + fill + + Color + + b + 0 + g + 0.8 + r + 0.6 + + + shadow + + Color + + a + 0.35 + b + 0.328823 + g + 0.328823 + r + 0.328823 + + Fuzziness + 1.5349206924438477 + ShadowVector + {0, 1} + + stroke + + Color + + b + 0 + g + 0.6 + r + 0.4 + + CornerRadius + 2 + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\b\fs24 \cf0 cache thread} + VerticalPad + 0 + + + + Bounds + {{391, 476.6673583984375}, {137.99996948242188, 23.499980926513672}} + Class + ShapedGraphic + FontInfo + + Color + + b + 0 + g + 0 + r + 0 + + Font + Roboto-BoldCondensed + Size + 12 + + ID + 206 + Magnets + + {1, 1} + {1, -1} + {-1, -1} + {-1, 1} + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + {-0.5, -0.233518} + {-0.49144199999999999, 0.26006299999999999} + {0.50711799999999996, -0.22408600000000001} + {0.50711799999999996, 0.267179} + {-0.27431, -0.474028} + {0.27977999999999997, -0.47847800000000001} + {0.29393799999999998, 0.54304399999999997} + {-0.28623199999999999, 0.55380399999999996} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.898039 + g + 0.709804 + r + 0.2 + + + shadow + + Color + + a + 0.35 + b + 0.328823 + g + 0.328823 + r + 0.328823 + + Fuzziness + 1.5349206924438477 + ShadowVector + {0, 1} + + stroke + + Color + + b + 0.93512 + g + 0.472602 + r + 0.333854 + + CornerRadius + 2 + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\b\fs24 \cf0 main thread} + VerticalPad + 0 + + + + Bounds + {{224.48312730407713, 421.74998497962952}, {137.99996948242188, 79.169700622558594}} + Class + ShapedGraphic + FontInfo + + Color + + b + 0 + g + 0 + r + 0 + + Font + Roboto-BoldCondensed + Size + 12 + + ID + 204 + Magnets + + {1, 1} + {1, -1} + {-1, -1} + {-1, 1} + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + {-0.5, -0.233518} + {-0.49144199999999999, 0.26006299999999999} + {0.50711799999999996, -0.22408600000000001} + {0.50711799999999996, 0.267179} + {-0.27431, -0.474028} + {0.27977999999999997, -0.47847800000000001} + {0.29393799999999998, 0.54304399999999997} + {-0.28623199999999999, 0.55380399999999996} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.2 + g + 0.733333 + r + 1 + + + shadow + + Color + + a + 0.35 + b + 0.328823 + g + 0.328823 + r + 0.328823 + + Fuzziness + 1.5349206924438477 + ShadowVector + {0, 1} + + stroke + + Color + + b + 0.131021 + g + 0.363196 + r + 0.725948 + + CornerRadius + 2 + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\b\fs24 \cf0 HTTP transaction, response parse, cache write (if applicable)} + VerticalPad + 0 + + + + Bounds + {{224.48311204528807, 390.50226273803713}, {137.99996948242188, 23.499996185302734}} + Class + ShapedGraphic + FontInfo + + Color + + b + 0 + g + 0 + r + 0 + + Font + Roboto-BoldCondensed + Size + 12 + + ID + 203 + Magnets + + {1, 1} + {1, -1} + {-1, -1} + {-1, 1} + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + {-0.5, -0.233518} + {-0.49144199999999999, 0.26006299999999999} + {0.50711799999999996, -0.22408600000000001} + {0.50711799999999996, 0.267179} + {-0.27431, -0.474028} + {0.27977999999999997, -0.47847800000000001} + {0.29393799999999998, 0.54304399999999997} + {-0.28623199999999999, 0.55380399999999996} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.2 + g + 0.733333 + r + 1 + + + shadow + + Color + + a + 0.35 + b + 0.328823 + g + 0.328823 + r + 0.328823 + + Fuzziness + 1.5349206924438477 + ShadowVector + {0, 1} + + stroke + + Color + + b + 0.131021 + g + 0.363196 + r + 0.725948 + + CornerRadius + 2 + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\b\fs24 \cf0 HTTP...} + VerticalPad + 0 + + + + Bounds + {{23.966245361328106, 366.5}, {137.99998474121094, 58.169700622558594}} + Class + ShapedGraphic + FontInfo + + Color + + b + 0 + g + 0 + r + 0 + + Font + Roboto-BoldCondensed + Size + 12 + + ID + 200 + Magnets + + {1, 1} + {1, -1} + {-1, -1} + {-1, 1} + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + {-0.5, -0.233518} + {-0.49144199999999999, 0.26006299999999999} + {0.50711799999999996, -0.22408600000000001} + {0.50711799999999996, 0.267179} + {-0.27431, -0.474028} + {0.27977999999999997, -0.47847800000000001} + {0.29393799999999998, 0.54304399999999997} + {-0.28623199999999999, 0.55380399999999996} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.2 + g + 0.733333 + r + 1 + + + shadow + + Color + + a + 0.35 + b + 0.328823 + g + 0.328823 + r + 0.328823 + + Fuzziness + 1.5349206924438477 + ShadowVector + {0, 1} + + stroke + + Color + + b + 0.131021 + g + 0.363196 + r + 0.725948 + + CornerRadius + 2 + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\b\fs24 \cf0 Request dequeued by NetworkDispatcher} + VerticalPad + 0 + + + + Bounds + {{35.121640869140606, 227.99999237060547}, {115.68917846679688, 58.169700622558594}} + Class + ShapedGraphic + FontInfo + + Color + + b + 0 + g + 0 + r + 0 + + Font + Roboto-BoldCondensed + Size + 10 + + ID + 4 + Magnets + + {1, 1} + {1, -1} + {-1, -1} + {-1, 1} + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + {-0.5, -0.233518} + {-0.49144199999999999, 0.26006299999999999} + {0.50711799999999996, -0.22408600000000001} + {0.50711799999999996, 0.267179} + {-0.27431, -0.474028} + {0.27977999999999997, -0.47847800000000001} + {0.29393799999999998, 0.54304399999999997} + {-0.28623199999999999, 0.55380399999999996} + + Shape + Rectangle + Style + + fill + + Color + + b + 0 + g + 0.8 + r + 0.6 + + + shadow + + Color + + a + 0.35 + b + 0.328823 + g + 0.328823 + r + 0.328823 + + Fuzziness + 1.5349206924438477 + ShadowVector + {0, 1} + + stroke + + Color + + b + 0 + g + 0.6 + r + 0.4 + + CornerRadius + 2 + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\b\fs24 \cf0 Request dequeued by CacheDispatcher} + VerticalPad + 0 + + + + Bounds + {{35.121638671874962, 107}, {118.18917846679688, 58.169700622558594}} + Class + ShapedGraphic + FontInfo + + Color + + b + 0 + g + 0 + r + 0 + + Font + Roboto-BoldCondensed + Size + 12 + + ID + 157 + Magnets + + {1, 1} + {1, -1} + {-1, -1} + {-1, 1} + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + {-0.5, -0.233518} + {-0.49144199999999999, 0.26006299999999999} + {0.50711799999999996, -0.22408600000000001} + {0.50711799999999996, 0.267179} + {-0.27431, -0.474028} + {0.27977999999999997, -0.47847800000000001} + {0.29393799999999998, 0.54304399999999997} + {-0.28623199999999999, 0.55380399999999996} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.898039 + g + 0.709804 + r + 0.2 + + + shadow + + Color + + a + 0.35 + b + 0.328823 + g + 0.328823 + r + 0.328823 + + Fuzziness + 1.5349206924438477 + ShadowVector + {0, 1} + + stroke + + Color + + b + 0.93512 + g + 0.472602 + r + 0.333854 + + CornerRadius + 2 + Draws + NO + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\b\fs24 \cf0 Request added to queue in priority order} + VerticalPad + 0 + + + + Class + Group + Graphics + + + Bounds + {{20.00199264625337, 331.00000000000006}, {145.92853034472586, 25.419100784950434}} + Class + ShapedGraphic + FontInfo + + Color + + a + 0.65 + b + 0 + g + 0 + r + 0 + + Font + Roboto-Condensed + Size + 12 + + ID + 1972 + Shape + Rectangle + Style + + fill + + Draws + NO + + shadow + + Draws + NO + + stroke + + Draws + NO + + + Text + + Pad + 2 + + + + Bounds + {{6.671600341796875, 356.41910654608148}, {172.58927917480466, 212.02962392266838}} + Class + ShapedGraphic + FontInfo + + Color + + a + 0.65 + w + 0 + + Font + Roboto-BoldCondensed + Size + 12 + + ID + 1973 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + Draws + NO + + shadow + + Draws + NO + + stroke + + Color + + b + 0.578326 + g + 0.578615 + r + 0.578453 + + CornerRadius + 5 + Pattern + 1 + + + Text + + VerticalPad + 10 + + TextPlacement + 0 + + + ID + 1971 + + + GridInfo + + GuidesLocked + NO + GuidesVisible + YES + HPages + 1 + ImageCounter + 1 + KeepToScale + + Layers + + + Lock + NO + Name + Layer 1 + Print + YES + View + YES + + + LayoutInfo + + Animate + NO + circoMinDist + 18 + circoSeparation + 0.0 + layoutEngine + dot + neatoSeparation + 0.0 + twopiSeparation + 0.0 + + LinksVisible + NO + MagnetsVisible + NO + MasterSheets + + ModificationDate + 2014-03-24 23:38:43 +0000 + Modifier + Katie McCormick + NotesVisible + NO + Orientation + 2 + OriginVisible + NO + PageBreaks + YES + PrintInfo + + NSBottomMargin + + float + 41 + + NSHorizonalPagination + + coded + BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG + + NSLeftMargin + + float + 18 + + NSPaperSize + + size + {612, 792} + + NSPrintReverseOrientation + + int + 0 + + NSRightMargin + + float + 18 + + NSTopMargin + + float + 18 + + + PrintOnePage + + ReadOnly + NO + RowAlign + 1 + RowSpacing + 36 + SheetTitle + Canvas 1 + SmartAlignmentGuidesActive + YES + SmartDistanceGuidesActive + YES + UniqueID + 1 + UseEntirePage + + VPages + 1 + WindowInfo + + CurrentSheet + 0 + ExpandedCanvases + + + name + Canvas 1 + + + Frame + {{159, 135}, {899, 874}} + ListView + + OutlineWidth + 142 + RightSidebar + + ShowRuler + + Sidebar + + SidebarWidth + 120 + VisibleRegion + {{-94, -1}, {764, 735}} + Zoom + 1 + ZoomValues + + + Canvas 1 + 1 + 1 + + + + + -- cgit v1.1