Статьи

Основы Android: Основы IntentService

Сегодня мы хотели бы познакомиться с одним из менее известных, но очень полезных типов услуг, которые вы, возможно, захотите использовать: IntentService.

IntentService ( android.app.IntentService ) — это простой тип службы, который можно использовать для обработки асинхронной работы из основного потока посредством запросов Intent. Каждое намерение добавляется в очередь IntentService и обрабатывается последовательно.

IntentService — это один из самых простых способов разгрузить «куски» обработки из потока пользовательского интерфейса вашего приложения в удаленную рабочую очередь. Нет необходимости запускать AsyncTask и управлять им каждый раз, когда у вас есть больше обработки. Вместо этого вы просто определяете свою собственную службу, упаковываете намерение с соответствующими данными, которые вы хотите отправить для обработки, и запускаете службу. Вы можете отправить данные обратно в приложение, просто отправив результат в виде объекта Intent и используя широковещательный приемник, чтобы перехватить результат и использовать его в приложении.

Мы предоставили пример приложения, которое иллюстрирует разницу между попыткой выполнить обработку в основном потоке пользовательского интерфейса (нет-нет ответа приложения) и выгрузить эту же обработку в IntentService. Код можно загрузить по ссылке для скачивания кода в верхней части этого руководства.

Во-первых, важно понимать, когда и зачем пользоваться услугами в целом. Хорошая причина использовать IntentService — это когда у вас есть работа, которая должна выполняться вне основного потока, чтобы приложение работало и работало быстро. Другая причина в том, что у вас может быть несколько запросов на обработку, и они должны быть поставлены в очередь и обработаны на лету.

Допустим, у нас есть приложение, которое должно выполнить «обработку». Мы хотели что-то простое, поэтому мы в основном определим обработку в этом случае как получение строкового параметра, выполнение «вещи» и возвращение строкового результата. Чтобы этот урок был простым, мы будем спать 30 секунд, делая вид, что делаем что-то полезное. В действительности, «вещи», вероятно, будут обработкой изображения, подключением к сети или какой-либо другой операцией блокировки.

Следовательно, если бы вся «обработка» происходила в основном приложении, у вас мог бы быть элемент управления EditText для ввода сообщения и элемент управления TextView для разделения результата. Вы можете поместить этот код в обработчик Button для запуска обработки. Код в обработчике нажатия кнопки в классе Activity приложения будет выглядеть примерно так:

1
2
3
4
5
6
7
EditText input = (EditText) findViewById(R.id.txt_input);
String strInputMsg = input.getText().toString();
 
SystemClock.sleep(30000);
 
TextView result = (TextView) findViewById(R.id.txt_result);
result.setText(strInputMsg + » » + DateFormat.format(«MM/dd/yy h:mmaa», System.currentTimeMillis()));

Результаты не идеальны в любом случае. Как только пользователь нажимает кнопку, все приложение перестает отвечать на запросы. Экран заморожен, пользователь не может продолжать свой бизнес, добавлять новые сообщения. Пользователь в основном должен ждать завершения обработки, прежде чем он сможет что-то сделать.

Мы бы предпочли, чтобы наша обработка не мешала работе приложения. Мы также хотели бы иметь возможность легко добавлять несколько запросов на обработку сообщений. Это идеальное время для использования IntentService! Итак, давайте реализуем один.

Создайте другой файл класса в своем проекте и добавьте заглушки для методов, которые вам нужно реализовать. Вы должны добавить конструктор с именем вашего нового сервиса. Вам нужно будет реализовать еще один метод с именем onHandleIntent (). Этот метод, где ваша обработка происходит. Любые данные, необходимые для каждого запроса на обработку, могут быть упакованы в дополнения к намерениям, например так (импорт, комментарии, обработка исключений удалена для ясности кода, подробности см. В полном исходном коде):

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
public class SimpleIntentService extends IntentService {
    public static final String PARAM_IN_MSG = «imsg»;
    public static final String PARAM_OUT_MSG = «omsg»;
 
    public SimpleIntentService() {
        super(«SimpleIntentService»);
    }
 
    @Override
    protected void onHandleIntent(Intent intent) {
 
        String msg = intent.getStringExtra(PARAM_IN_MSG);
        SystemClock.sleep(30000);
        String resultTxt = msg + » «
            + DateFormat.format(«MM/dd/yy h:mmaa», System.currentTimeMillis());
    }
}

Обратите внимание, что мы также определяем дополнительные параметры намерения для входящих и исходящих данных намерения. Мы используем дополнительный PARAM_IN_MSG для данных входящего сообщения. Скоро мы будем использовать дополнительный PARAM_OUT_MSG для отправки результатов обратно в основное приложение.

Затем вам нужно запустить службу из активности вашего приложения. Добавьте второй элемент управления Button, который вместо выполнения обработки в главном потоке вместо этого делегирует обработку новой службе. Новый обработчик кнопок выглядит так:

1
2
3
4
5
EditText input = (EditText) findViewById(R.id.txt_input);
String strInputMsg = input.getText().toString();
Intent msgIntent = new Intent(this, SimpleIntentService.class);
msgIntent.putExtra(SimpleIntentService.PARAM_IN_MSG, strInputMsg);
startService(msgIntent);

Код для сервисного метода обработки довольно прост. Сначала создается экземпляр Intent, и любые данные (например, текст сообщения) упаковываются в намерение с использованием дополнительных функций. Наконец, IntentService запускается с помощью вызова startService ().

Служба вступает во владение отсюда, перехватывая каждый намеренный запрос, обрабатывая его и закрывая себя, когда все это сделано. Основной пользовательский интерфейс остается отзывчивым на протяжении всей обработки, что позволяет пользователю продолжать взаимодействовать с приложением. Пользователь может вводить несколько сообщений, снова и снова нажимать кнопку, и каждый запрос добавляется в рабочую очередь службы и обрабатывается. В общем, лучшее решение.

Но мы еще не закончили.

Ваш IntentService теперь может выполнять свою работу по обработке, но он нам нужен, чтобы информировать основное действие приложения при обработке каждого запроса, чтобы пользовательский интерфейс мог быть обновлен. Это действительно имеет значение только во время выполнения действия, поэтому мы будем использовать простую модель широковещательного отправителя / получателя.

Давайте начнем с определения подкласса BroadcastReceiver в основной деятельности.

01
02
03
04
05
06
07
08
09
10
11
public class ResponseReceiver extends BroadcastReceiver {
   public static final String ACTION_RESP =
      «com.mamlambo.intent.action.MESSAGE_PROCESSED»;
    
   @Override
    public void onReceive(Context context, Intent intent) {
       TextView result = (TextView) findViewById(R.id.txt_result);
       String text = intent.getStringExtra(SimpleIntentService.PARAM_OUT_MSG);
       result.setText(text);
    }
}

Метод onReceive () выполняет всю работу. Он обновляет элемент управления TextView действия на основе намеренных дополнительных данных, упакованных во входящий результат.

Примечание. Если вы обновляли базу данных или общие настройки, пользовательский интерфейс может получить эти изменения альтернативными способами. В этих случаях накладные расходы на широковещательный приемник не потребуются.

Затем вам нужно отправить широковещательную рассылку из метода onHandleIntent () класса IntentService после завершения обработки и получения результата, например:

1
2
3
4
5
6
// processing done here….
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(ResponseReceiver.ACTION_RESP);
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
broadcastIntent.putExtra(PARAM_OUT_MSG, resultTxt);
sendBroadcast(broadcastIntent);

Чтобы отправить результат обратно в основное приложение, мы упаковываем другое намерение, вставляем данные результата как дополнительные и отправляем их обратно, используя метод sendBroadcast ().

Наконец, вы должны создать экземпляр и зарегистрировать получателя, которого вы определили в своей деятельности. Зарегистрируйте получателя в методе onCreate () с соответствующим фильтром намерений, чтобы перехватить конкретный намеренный результат, отправляемый из IntentService.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
public class IntentServiceBasicsActivity extends Activity {
    private ResponseReceiver receiver;
     
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
         
        IntentFilter filter = new IntentFilter(ResponseReceiver.ACTION_RESP);
        filter.addCategory(Intent.CATEGORY_DEFAULT);
        receiver = new ResponseReceiver();
        registerReceiver(receiver, filter);
    }
}

Результат: каждый раз, когда IntentService заканчивает обработку запроса, он запускает трансляцию с результатом. Основная деятельность может прослушивать широковещательную рассылку, а метод onReceive () получателя широковещательной рассылки делает все остальное, обновляя UI соответствующим образом. Не забудьте также вовремя отменить регистрацию получателя (рекомендуется onPause ()).

Перенос работы из основного потока пользовательского интерфейса приложения в рабочую очередь в IntentService — это простой и эффективный способ обработки нескольких запросов. Это делает ваше основное приложение отзывчивым, а ваши пользователи — счастливыми. Для многих целей использование IntentService может быть проще и более желательным, чем AsyncTask, который ограничен одним выполнением, или Thread, который имеет больше накладных расходов на кодирование.

Разработчики мобильных приложений Лорен Дарси и Шейн Кондер являются соавторами нескольких книг по разработке Android: углубленная книга по программированию под названием « Разработка беспроводных приложений для Android, второе издание» и « Самс научи себя разработке приложений для Android за 24 часа, второе издание» . Когда они не пишут, они тратят свое время на разработку мобильного программного обеспечения в своей компании и оказание консультационных услуг. С ними можно связаться по электронной почте androidwirelessdev+mt@gmail.com , через их блог на androidbook.blogspot.com и в Twitter @androidwireless .

Купить Android-разработку беспроводных приложений 2nd Edition Купить Самс научи себя разработке приложений для Android за 24 часа Второе издание Код Мамламбо в Код-Каньоне

На Envato Market также имеется огромный выбор шаблонов приложений для Android, которые помогут вам начать работу над проектами разработки для Android.