Фоновые сетевые вызовы - iOS - PullRequest
6 голосов
/ 28 июля 2011

Мне нужно реализовать отправку некоторых данных на веб-сервер в фоновом режиме.Просто для пояснения, под «на заднем плане», я не имею в виду обычный способ показа вращающегося значка и отправки данных в веб-сервис, используя что-то вроде AsyncTask или ASIHTTPRequest [request startAsynchronous] метода.Мне нужно поддерживать очередь данных, которую поток может асинхронно начинать обрабатывать и отправлять в веб-службу, пока пользователь работает в приложении.

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

Спасибо,
Teja.

Ответы [ 4 ]

3 голосов
/ 03 августа 2011

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

Также разрешает зависимости между очередями;например, я использую две очереди в своем приложении:

Первые планируют загрузку изображений с максимальной одновременностью 2 одновременно в фоновом режиме.Каждая загрузка изображения имеет соответствующий обработчик завершения (как NSBlockOperation), который зависит от завершения загрузки изображения.Эти операции выполняются на [NSOperationQueue mainQueue], который работает в основном потоке, что позволяет им обновлять пользовательский интерфейс (в частности, соответствующий UIImageView).

Обратите внимание, что NSOperation и NSOperationQueue не предназначены для сетитолько запросы, но любая операция, которая может быть разделена на элементарные задачи и запланирована одновременно.

Здесь - вводные документы Apple по теме.

2 голосов
/ 28 июля 2011

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

Затем, чтобы реализовать очередь, предлагаю вам взглянуть на IntentService (http://developer.android.com/reference/android/app/IntentService.html)

из документов:

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

Этот шаблон «обработчик рабочей очереди» обычно используется для разгрузки задач. из основного потока приложения. Класс IntentService существует для упростить эту схему и позаботиться о механике. Чтобы использовать это, расширить IntentService и реализовать onHandleIntent (Intent). IntentService получит Intents, запустит рабочий поток и остановите службу соответствующим образом.

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

Если ваше приложение достаточно простое, вы можете использовать sendBroadCast () для обмена информацией и уведомлениями между вашей деятельностью и IntentService

0 голосов
/ 09 августа 2011

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

Прежде всего, я предлагаю вам выполнять все сетевые вызовы в главном потоке асинхронно , а не синхронно, используя делегата.Таким образом, сериализация / синхронизация / параллелизм не является проблемой.А поскольку классы являются сетевыми делегатами, я просто отправил один класс туда, где у нового соединения есть новый экземпляр делегата.

[[NSURLConnection alloc] initWithRequest:request delegate:del] autorelease];

e.g.
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
0 голосов
/ 05 августа 2011

Создать синглтон, который инкапсулирует поток:

В инициализации вашего объекта:

[NSThread detachNewThreadSelector:@selector(mainPosterThread) toTarget:self withObject:nil];

- (void)mainDownloaderThread
{

    if( [NSThread respondsToSelector:@selector(setThreadPriority:)] )
    {
        [NSThread setThreadPriority:0.1];
    }
    NSString *urlToDownload = nil;
    while(shouldRun)
    {
        // Take next data to post in a queue (lastObject of a NSArray for example)
        if( nextDataToPost )
        {
             // Post
        }
        else
        {
             // Sleep for some time.
        }
    }
}

У вас также могут быть методы для остановки / запуска потока, когда приложение работает в фоновом режиме / на переднем плане на устройстве с поддержкой многозадачности. Если многозадачность не поддерживается, сохраните данные поста в очереди во время остановки (если не слишком долго) и восстановите их при запуске. Самая большая проблема - это возможность отменить текущую загрузку, пока приложение будет закрыто.

...