Ожидание Android: UrlJsonAsyncTask
- Исходный код для этой статьи: UrlJsonAsyncTaskTest на GitHub
- Загрузите и установите приложение для Android: UrlJsonAsyncTaskTest.apk (Android 2.2 или более поздняя версия )
- Вы также можете отсканировать этот QR-код, чтобы загрузить его на свой телефон Android:
обзор
Я даже не могу сосчитать, сколько раз мне приходилось загружать ProgressDialog в Android, запрашивать JSON с удаленного URL-адреса, а затем возвращать управление обратно в приложение после завершения запроса. Это невероятно распространенный поток управления, и мне надоело снова и снова. Я уверен, что я не одинок.
Чтобы сохранить эту СУХУЮ ситуацию, класс UrlJsonAsyncTask в моей коллекции помощников Android, com.savagelook.android , посвящен вышеупомянутой задаче. Это сокращает то, что может быть более 80 строк кода для каждой задачи, до 15 или менее.
Прежде чем копаться, вот несколько вещей, чтобы рассмотреть.
- Это не базовое руководство, поэтому предполагается, что вы знакомы с Android. В частности, вы должны понимать, как Android использует Intents, Activity и базовую обработку событий.
- Хотя в этом нет необходимости, вам будет все легче понять, если вы хотя бы знакомы с классом Android AsyncTask .
- Я использую несколько других классов в com.savagelook.android в
UrlJsonAsyncTask
которые вы, скорее всего, не узнаете, например JsonHelper и Lazy.Ex. Все они с открытым исходным кодом и свободно доступны на GitHub. - Я не понимаю, как работает
UrlJsonAsyncTask
, а как его использовать. Будьте услышаны в комментариях, если хотите, чтобы я продолжил.
UrlJsonAsyncTaskTest
Лучший способ узнать, как UrlJsonAsyncTask
может ускорить вашу разработку, — увидеть ее в действии. Вы можете следовать приведенным ниже фрагментам кода или полностью раскрыть исходный код проекта, на котором я их основываю. Проект UrlJsonAsyncTaskTest, его можно бесплатно загрузить или клонировать с GitHub.
Приложение специально сделано как можно голее. Мы просто собираемся создать кнопку в нашем основном UrlJsonAsyncTask
, которая запустит UrlJsonAsyncTask
а затем вернет результат своего запроса в новом UrlJsonAsyncTask
.
Прежде чем мы перейдем к Кодексу …
UrlJsonAsyncTask делает только одно предположение «соглашение о конфигурации». Для того чтобы все функции обработки ошибок и тайм-аута обрабатывались под капотом, ваш JSON должен быть в следующем формате:
{ "success": true|false, "info": "an error message to present to the user when success is false", "data": YOUR_DATA }
-
success
— это логическое значение, указывающее, был ли запрос успешным на стороне сервера. -
info
дает пользователю описательное, но очищенное описание ошибки. -
data
— это фактические данные, которые вы хотите вернуть из запроса.YOUR_DATA
может быть любым значением или даже другим объектом или массивом JSON.
(Скучный) код
Хорошо, давайте сначала уберем скучные вещи. Вот изменения, которые необходимо внести в основной проект Android, чтобы он выглядел как UrlJsonAsyncTaskTest , если вам было лень скачивать / клонировать его самостоятельно.
AndroidManifest.xml
Вам нужно добавить 2 вещи. Во-первых, разрешите Android общаться с Интернетом, добавив условие uses-permission
в элементе manifest.
<uses-permission android:name="android.permission.INTERNET" />
Во-вторых, вам нужно добавить второе действие, которое мы откроем после успешного вызова UrlJsonAsyncTask
в элементе application
. Он будет соответствующим образом назван SecondActivity
.
<activity android:name=".SecondActivity"/>
разреш / макет / main.xml
Это макет XML, который мы применим к MainActivity
. Вот кнопка, которую мы будем использовать для запуска UrlJsonAsyncTask
.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:id="@+id/mainButton" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="Get Remote JSON"/> </LinearLayout>
разреш / макет / second.xml
Это макет XML для SecondActivity
. Здесь в TextView мы разместим строку JSON, которая возвращается из нашего вызова UrlJsonAsyncTask
.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:id="@+id/jsonText" android:layout_width="fill_parent" android:layout_height="wrap_content"/> </LinearLayout>
(Интересный) код
Теперь пришло время фактически расширить, создать экземпляр и вызвать нашу UrlJsonAsyncTask
. Мы сделаем все это в MainActivity
всего за несколько строк кода. Если вас не интересует весь пример проекта UrlJsonAsyncTaskTest, и вы просто хотите знать, как использовать UrlJsonAsyncTask
в ваших собственных проектах, это раздел, на который вам нужно обратить внимание .
MainActivity.java
Первое, что нам нужно сделать, это создать наш собственный класс, который расширяет UrlJsonAsyncTask
. Это позволит нам использовать встроенную функциональность, предоставляя нам свободу определять, как обрабатывается полученный JSON. Мы делаем это как private class
член private class
MainActivity
. Прочитайте комментарии для деталей в каждом разделе.
private class MyTask extends UrlJsonAsyncTask { // Create a default constructor public MyTask(Context context) { super(context); } // onPostExecute(JSONObject) is what is called when the UrlJsonAsyncTask completes. // The JSONObject represents the JSON returned by the remote URL we queried. @Override protected void onPostExecute(JSONObject json) { try { // call validateJson() to ensure well formatted JSON this.validateJson(json); // If the JSON is returned successfully and well formatted, send the // JSON "data" as String Extra "json" to SecondActivity Intent intent = new Intent(context, SecondActivity.class); intent.putExtra("json", json.getString("data").toString()); startActivity(intent); } catch (JSONException e) { // If there were exceptions handling the JSON... Toast.makeText(context, this.getMessageError(), Toast.LENGTH_SHORT).show(); } catch (Exception e) { // All other uncaught exceptions, like HTTP or IO problems... Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show(); } finally { // You MUST call this or your UrlJsonAsyncTask's ProgressDialog will // not close. super.onPostExecute(json); } } }
Теперь, когда мы создали MyTask
, все, что нам нужно сделать, это создать его экземпляр, дать ему (удаленный) URL-адрес и позволить основному UrlJsonAsyncTask
выполнить остальную часть работы. Чтобы сделать его интерактивным, мы сделаем все это в обработчике mainButton
кнопки mainButton
в функции onCreate () MainActivity
.
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button button = (Button)findViewById(R.id.mainButton); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { // The URL that'll we'll test against String remoteJsonUrl = "http://savagelook.com/misc/UrlJsonAsyncTaskTest.php"; // assign a context and loading message MyTask task = new MyTask(MainActivity.this); task.setMessageLoading("Getting remote JSON..."); // Launch the UrlJsonAsyncTask with the test URL task.execute(remoteJsonUrl); } }); }
Если все идет хорошо, MyTask.onPostExecute()
будет вызван, как только эта задача вернет запрошенный JSON из http://savagelook.com/misc/UrlJsonAsyncTaskTest.php
.
SecondActivity.java
Просто чтобы убедиться, что все идет по плану, мы отобразим строку данных JSON в SecondActivity
. Для этого мы добавим следующие несколько строк кода в SecondActivity.onCreate()
.
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.second); // Get the JSON string we assigned to the intent in MyTask.onPostExecute() String jsonString = this.getIntent().getStringExtra("json"); // assign the JSON string to the TextView TextView textView = (TextView)findViewById(R.id.jsonText); textView.setText(jsonString); }
Вот и все. Теперь у вас должен быть UrlJsonAsyncTask, успешно подключающийся к удаленному URL-адресу и запрашивающий JSON, в то время как наличие ProgressDialog позволяет пользователю знать, что происходит. Как я уже говорил ранее, это очень распространенная задача, а теперь очень простая.
Резюме
В конце концов, мы достигаем не ракетостроения. Все, что мы делаем, это создаем типичный поток управления для приложения, которое опирается на удаленные данные. Моя цель состояла в том, чтобы сделать этот поток как можно более простым, не жертвуя слишком большой гибкостью.
Я настоятельно рекомендую вам проверить репозиторий GitHub для всего моего кода com.savagelook.android . Получить под капотом и посмотреть, как именно UrlJsonAsyncTask
делает то, что он делает. Попробуйте некоторые другие свойства класса, такие как время ожидания и повторные попытки. Взгляните и на другие вспомогательные классы. Кроме того, не стесняйтесь клонировать и внести свой вклад обратно.
Надеемся, что это поможет вам тратить меньше времени на управление и больше времени на уникальную функциональность, предоставляемую вашими приложениями для Android.