2012-04-19 3 views
0

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

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

Поскольку для удаленной службы разрешено иметь только один поток для всех приложений, использующих его одновременно (только одно подключение по Bluetooth), я выбрал метод обмена сообщениями по AIDL.

Моя проблема заключается в том, что я хотел предоставить синхронный метод в моем общедоступном API, но служба возвращается в обработчике, и, насколько я понял, обработчик всегда будет ждать завершения текущей задачи ... Так есть ли способ получить ответ в другом потоке?

код синхронного метода, как хотелось бы, чтобы это было:

responseDataSync = new Sync<ResponseData>(); 

    // Send message 
    Message msg = Message.obtain(null, Constants.DATA, 1, 0); 

    send(msg); 

    try { 
     ResponseData responseData = responseDataSync.get(); 

     // with responseDataSync using a countdown latch to synchronize... 
// but it never fires thanks to the handler. 
//etc... 

Спасибо заранее. Надеюсь, мой вопрос был несколько понятен ...;)

/EDIT: Мне нужен какой-то метод, который возвращает данные с сервера. как

public ResponseData returnResponse(Data dataToSend) 

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

+0

у вас есть (удаленная) служба, которую вы распространяете через apk и публичный api, который должен быть включен в другие приложения, которые хотят использовать эту услугу? – zapl

+0

Ты меня достал. ;) Библиотека имеет дополнительные функции и должна сделать доступ к службе максимально простой - отсюда необходимость синхронизированного метода – domenukk

ответ

3

Handler связан с одной очередью сообщений. Если вы отправите Message из любой темы, он будет выставлен там.

Поток, который получает все сообщения, выдает соответствующее сообщение из очереди и обрабатывает его - один за другим.

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

Edit: создать обработчик, который обрабатывает сообщения в фоновом потоке:

HandlerThread ht = new HandlerThread("threadName"); 
ht.start(); 
Looper looper = ht.getLooper(); 
Handler.Callback callback = new Handler.Callback() { 

    @Override 
    public boolean handleMessage(Message msg) { 
     // handled messages are handled in background thread 
     return true; 
    } 
}; 
Handler handler = new Handler(looper, callback); 

handler.sendEmptyMessage(1337); 

Edit2: ждать сообщения может работать как этот

// available for all threads somehow 
final Object waitOnMe = new Object(); 

HandlerThread ht = new HandlerThread("threadName"); 
ht.start(); 
Looper looper = ht.getLooper(); 
Handler.Callback callback = new Handler.Callback() { 

    @Override 
    public boolean handleMessage(Message msg) { 
     // handled messages are handled in background thread 
     // then notify about finished message. 
     synchronized (waitOnMe) { 
      waitOnMe.notifyAll(); 
     } 
     return true; 
    } 
}; 
Handler handler = new Handler(looper, callback); 

// in a different Thread: 
synchronized (waitOnMe) { 
    handler.sendEmptyMessage(1337); 
    try { 
     waitOnMe.wait(); 
    } catch (InterruptedException e) { 
     // we should have gotten our answer now. 
    } 
} 
+0

Спасибо, я это понял. Это моя проблема. Я хотел иметь синхронный метод, например public SomeValue returnSomeValue (SomeParameter someParameter) , но я не могу дождаться результата от службы, потому что мой обработчик ничего не вернет, пока я застрял в выполнении метода ... – domenukk

+0

Хорошо, я вижу. Это немного сложнее: в основном вам нужно будет поместить механизм, который сначала отправит сообщение в вашу службу, а затем ждет сообщения, которое вы получите из службы внутри 'returnSomeValue()'. Другой возможностью является регулярная служба с интерфейсом AIDL, которая обрабатывает это внутренне. Вы можете вызвать реальные методы в такой службе, но вам все равно придется управлять сервисным соединением в 'returnSomeValue()', если вы не хотите, чтобы пользователь это делал. – zapl

+0

Мне нужен первый подход. Проблема с AIDL заключается в том, что мне пришлось бы переписать в основном все и что я должен был бы реализовать синхронизацию, которая приходит естественным образом с помощью Messengers. Вы не знаете, как ждать обработчика? Поскольку обработчик синхронизирован, я просто не могу найти какой-либо подход, как функция может подождать. (Пока функция ожидает, что обработчик не возвращается.) Могу ли я поместить обработчик в другой поток? Я наткнулся на HandlerThread, но не мог понять, помогает ли мне ... – domenukk