Эта статья была обновлена 21 декабря 2016 года. В частности: новая запись, обновленный устаревший код и добавлен новый раздел для загрузки изображений.
Сеть с Volley в Android
Сеть была вокруг с нулевого дня мобильных технологий, и Android не отличается. Изменился способ обработки сетевых операций. Центром сетевых библиотек, таких как Volley, была автоматизация сетевых операций.
До HoneyComb сетевые вызовы выполнялись из основного потока, а в последующих версиях Android сетевые запросы выполнялись асинхронно из основного потока. Чтобы выполнить сетевой вызов, разработчику необходимо внедрить Asynctask
в другом потоке, отличном от основного потока приложения, NetworkOnMainThreadException
будет NetworkOnMainThreadException
.
Краткий обзор залпа
Volley — это сетевая библиотека для Android, которая управляет сетевыми запросами. Он объединяет самые важные функции, которые вам нужны, такие как доступ к API-интерфейсам JSON, загрузка изображений и запросов String в более простой в использовании пакет.
Используя Volley для сетевых операций, вы избегаете стандартного способа управления сетью, HttpURLConnection
. Другая причина — асинхронность. Volley обрабатывает асинхронность сама по себе, нет необходимости создавать Asynctask
вручную.
Основываясь на документации , ядром каждой сетевой операции, выполняемой Volley, является RequestQueue
. Работа с Volley выполняется путем создания RequestQueue
и передачи ему объектов Request
. RequestQueue
управляет рабочими потоками для выполнения сетевых операций, чтения и записи в кэш и анализа ответов.
Volley предлагает множество функций, как указано в его документации :
- Автоматическое планирование сетевых запросов.
- Несколько одновременных сетевых подключений.
- Кэширование.
- Запрос приоритизации.
- Отмена текущих запросов API.
Это основные преимущества, которые предоставляет эта библиотека, и основное внимание в этой статье.
Импортировать залп, добавить разрешения
Прежде чем начать работу с Volley, вам необходимо настроить проект Android.
Создайте новый проект Android. Откройте build.gradle(Module: app)
и добавьте следующую зависимость.
dependencies { //... compile 'com.android.volley:volley:1.0.0' }
В AndroidManifest.xml
добавьте интернет-разрешение.
< uses-permission android:name = "android.permission.INTERNET" />
Стандартные сетевые запросы
Как я упоминал ранее, ядром каждой сетевой операции, выполняемой Volley, является RequestQueue
. Каждый запрос к сети передается в объекты RequestQueue
через объекты Request
.
Существует три типа запросов: запросы JSON, запросы изображений и запросы строк. Я рассмотрю каждый из этих типов с пояснениями и примерами кода.
На данный момент в MainActivity
onCreate()
RequestQueue
инициируйте RequestQueue
.
RequestQueue requestQueue; @Override protected void onCreate (Bundle savedInstanceState) { //... requestQueue = Volley.newRequestQueue( this ); // 'this' is the Context }
JSON Requests
У Volley есть Запросы для JSONObject
и JSONArray
. Структура JSONRequest и большинство классов запросов, включенных в Volley, используют конструкторы, подобные следующим.
JsonObjectRequest request JsonObjectRequest(RequestMethod, URL, null , new ResponseListener(), new ErrorListener());
Параметры, передаваемые в конструктор:
-
RequestMethod
(GET, POST, PUT, DELETE и т. Д.) -
URL
: строка URL требуемого объекта -
JSONObject
: необязательный объект, опубликованный с запросом,JSONObject
, если объект не опубликован -
ResponseListener
: слушатель ответа, чей метод обратного вызова будет содержать ответ -
ErrorListener
:Response.ErrorListener
, метод обратного вызова которого будет содержать любую проблему с запросом.
Следующие фрагменты кода являются полной реализацией JsonObjectRequest
и JsonArrayRequest
соответственно.
/*Json Request*/ String url = "https://json_url/" ; JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url, null , new Response.Listener<JSONObject>() { @Override public void onResponse (JSONObject response) { } }, new Response.ErrorListener() { @Override public void onErrorResponse (VolleyError error) { } }); //add request to queue requestQueue.add(jsonObjectRequest); JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, url, null , new Response.Listener<JSONArray>() { @Override public void onResponse (JSONArray response) { } }, new Response.ErrorListener() { @Override public void onErrorResponse (VolleyError error) { } }); //add request to queue requestQueue.add(jsonArrayRequest);
Теперь, когда я показал, как получать данные JSON в Android, давайте посмотрим, как публиковать данные с помощью Volley.
Запрос имеет тот же формат, что и прием данных JSON, за исключением того, что вы должны указать JSONObject
отправленный с запросом, и заголовки запроса для отправки данных от клиента на сторону сервера.
/*Post data*/ Map<String, String> jsonParams = new HashMap<String, String>(); jsonParams.put( "email" , "[email protected]" ); jsonParams.put( "username" , "user" ); jsonParams.put( "password" , "pass" ); JsonObjectRequest postRequest = new JsonObjectRequest( Request.Method.POST, URL, new JSONObject(jsonParams), new Response.Listener<JSONObject>() { @Override public void onResponse (JSONObject response) { } }, new Response.ErrorListener() { @Override public void onErrorResponse (VolleyError error) { // Handle Error } }) { @Override public Map<String, String> getHeaders () throws AuthFailureError { HashMap<String, String> headers = new HashMap<String, String>(); headers.put( "Content-Type" , "application/json; charset=utf-8" ); headers.put( "User-agent" , System.getProperty( "http.agent" )); return headers; } }; requestQueue.add(postRequest);
Обратите внимание, что заголовки запроса могут изменяться в зависимости от варианта использования разработки.
Строка запроса
Этот тип запроса используется для извлечения данных с сервера в виде строки.
/*String Request*/ String url = "https://string_url/" ; StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { @Override public void onResponse (String response) { } }, new Response.ErrorListener() { @Override public void onErrorResponse (VolleyError error) { } }); //add request to queue requestQueue.add(stringRequest);
Структура StringRequest
содержит метод запроса (POST или GET), URL-адрес источника String, Response.Listener
и Response.ErrorListener
. JsonRequest
же, как JsonRequest
.
Запрос изображения
Volley предлагает несколько способов загрузки изображений в Android. Я рассмотрю их все, чтобы объяснить их различия и привести некоторые примеры кода.
ImageRequest
ImageRequest
— это способ загрузки изображений для получения изображения по заданному URL. Структура этого сетевого вызова аналогична другим ранее представленным запросам.
Следующий код является примером ImageRequest
для загрузки изображения в ImageView
.
int maxWidth = ...; int maxHeight = ...; String URL = "http://image_url.png" ; ImageRequest imageRequest = new ImageRequest(URL, new Response.Listener<Bitmap>() { @Override public void onResponse (Bitmap response) { // Assign the response to an ImageView ImageView imageView = (ImageView) findViewById(R.id.imageView); imageView.setImageBitmap(response); } }, maxWidth, maxHeight, null ); //add request to queue requestQueue.add(imageRequest);
Структура ImageRequest
проста. Ему нужны URL-адрес изображения, прослушиватель ответа, метод обратного вызова которого будет содержать растровое изображение в качестве ответа, maxWidth
и maxHeight
, формат Config для декодирования растрового изображения и Response.ErrorListener
для любых ошибок ответа. Добавьте запрос в RequestQueue
а RequestQueue
среда выполнения Android.
ImageLoader
ImageLoader
— это вспомогательный класс для обработки загрузки и кэширования изображений с удаленных URL-адресов. Этот запрос полезен для большого количества ImageRequest
. В соответствии с документацией ImageLoader
предоставляет кэш в памяти перед обычным кешем Volley, что важно для предотвращения мерцания.
NetworkImageView
NetworkImageView
— эффективный способ заменить ImageView
когда изображения загружаются из сети.
Следующие фрагменты кода обеспечивают реализацию двух последних разделов загрузки изображений с помощью Volley. Следующий класс VolleySingleton
является реализацией RequestQueue
. Этот одноэлементный класс имеет возможности кэширования с LRU-кешем в памяти. LruCache
настроен на хранение до 30 элементов.
import android.content.Context; import android.graphics.Bitmap; import android.support.v4.util.LruCache; import android.util.Log; import com.android.volley.RequestQueue; import com.android.volley.toolbox.ImageLoader; import com.android.volley.toolbox.Volley; public class VolleySingleton { private static VolleySingleton singletonInstance = null ; private RequestQueue requestQueue; private ImageLoader imageLoader; private VolleySingleton (Context context) { requestQueue = Volley.newRequestQueue(context); imageLoader = new ImageLoader( this .requestQueue, new ImageLoader.ImageCache() { private final LruCache<String, Bitmap> lruCache = new LruCache<String, Bitmap>( 30 ); //30 -> the maximum number of entries in the cache. public void putBitmap (String url, Bitmap bitmap) { lruCache.put(url, bitmap); Log.d( "CachedItems" , String.valueOf(lruCache.size())); } public Bitmap getBitmap (String url) { return lruCache.get(url); } }); } public static VolleySingleton getInstance (Context context) { if (singletonInstance == null ) { singletonInstance = new VolleySingleton(context); } return singletonInstance; } public RequestQueue getRequestQueue () { return this .requestQueue; } public ImageLoader getImageLoader () { return this .imageLoader; } }
Теперь, VolleySingleton
класс VolleySingleton
настроен, давайте загрузим изображение в NetworkImageView
. Но сначала добавьте экземпляр в файл макета Activity. Вот пример:
< com.android.volley.toolbox.NetworkImageView android:id = "@+id/networkImageView" android:layout_width = "match_parent" android:layout_height = "wrap_content" />
Наконец, загрузите изображение в NetworkImageView
. В MainActivity
onCreate()
метода onCreate()
добавьте этот код.
private ImageLoader imageLoader; private NetworkImageView imageView; private static final String IMAGE_URL = "https://the_images_url.jpg" ; @Override protected void onCreate (Bundle savedInstanceState) { //... imageLoader = VolleySingleton.getInstance(getApplicationContext()).getImageLoader(); imageView = (NetworkImageView) findViewById(R.id.networkImageView); imageView.setImageUrl(IMAGE_URL, imageLoader); }
Чтобы убедиться, что кеш работает правильно, я добавил оператор Log
в класс VolleySingleton
. Запустите проект и проверьте Вход в Android Studio. Каждый раз, когда новое изображение кэшируется, устройство печатает несколько кэшированных элементов.
Запрос приоритетов
Обработка сетевых запросов означает установление приоритетов в отношении того, что необходимо и насколько быстро требуется ответ, поскольку работа в сети является операцией в реальном времени.
Volley обрабатывает запросы от более высоких приоритетов к более низким приоритетам, в порядке очереди. Метод setPriority()
, поэтому для определения приоритета запроса требуется некоторая работа.
Вот пример пользовательского класса JsonObjectRequest
который может делать приоритетные запросы. Основное внимание в этом классе уделяется переопределенному getPriority()
. Когда запрос добавляется в очередь, этот метод возвращает приоритет, назначенный ему setPriority()
, или возвращает Priority.HIGH
назначенный внутри класса, но он не будет искать приоритет вне этого класса.
Та же самая структура применяется ко всем другим типам запросов.
public class CustomPriorityRequest extends JsonObjectRequest { Priority priority = Priority.HIGH; public CustomPriorityRequest ( int method, String url, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) { super (method, url, jsonRequest, listener, errorListener); } public CustomPriorityRequest (String url, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) { super (url, jsonRequest, listener, errorListener); } @Override public Priority getPriority () { return priority; } public void setPriority (Priority p){ priority = p; } }
Создание запроса с этим новым классом аналогично стандартным запросам. У вас есть возможность установить приоритет запроса перед добавлением его в очередь.
CustomPriorityRequest customPriorityRequest = new CustomPriorityRequest( Request.Method.GET, URL, null , new Response.Listener<JSONObject>(), new Response.ErrorListener()); customPriorityRequest.setPriority(Request.Priority.IMMEDIATE); requestQueue.add(customPriorityRequest);
Некоторые доступные приоритеты: Приоритет. НИЗКИЙ, Приоритет. НОРМАЛЬНЫЙ, Приоритет. ВЫСОКИЙ и Приоритет. НЕМЕДЛЕННЫЙ.
Отмена запросов
Еще одним полезным инструментом в Volley является возможность отмены запросов. Отмена запросов полезна, когда пользователь закрывает приложение или выполняет действие, в результате которого не используются ответы на запросы залпа. Нет смысла выполнять оставшиеся запросы в очереди, поэтому мы отменяем их в onStop()
.
Самый простой способ отменить запросы в Volley — это добавить тег к запросу, а когда запросы в очереди нужно отменить, вызовите метод cancelAll()
. Это отменит все запросы, указанные с этим конкретным тегом.
request.setTag( "TAG" ); requestQueue.cancelAll( "TAG" );
Как только cancelAll()
выполняется из основного потока, остальные ответы не будут доставлены.