Не односторонние декларации в Android.AIDL гарантирует, что метод будет вызван в отдельном потоке?
Я разрабатываю фреймворк для клиент-серверного приложения для телефонов на Android. Я довольно Новичок как в Java, так и в Android (но не новичок в программировании вообще или в потоковом программировании в частности).
Иногда мой сервер и клиент будут находиться в одном и том же процессе, а иногда они будут находиться в разных процессах, в зависимости от конкретного случая использования. Клиентский и серверный интерфейсы выглядят примерно так: следующее:
IServer.aidl:
package com.my.application;
interface IServer {
/**
* Register client callback object
*/
void registerCallback( in IClient callbackObject );
/**
* Do something and report back
*/
void doSomething( in String what );
.
.
.
}
IClient.aidl:
package com.my.application;
oneway interface IClient {
/**
* Receive an answer
*/
void reportBack( in String answer );
.
.
.
}
Теперь вот где это становится интересным. Я могу предвидеть случаи использования, когда клиент вызывает IServer.doSomething()
, который в свою очередь вызывает IClient.reportBack()
, и на основе того, что сообщается обратно, IClient.reportBack()
должен сделать еще один вызов IClient.doSomething()
.
Проблема здесь в том, что IServer.doSomething()
в целом не будет реентерабельным. Это нормально, если IClient.reportBack()
всегда вызывается в новом потоке. В таком случае, я могу убедиться, что реализация из IServer.doSomething()
всегда synchronized
соответственно, так что вызов из Нового потока блокируется до тех пор, пока не вернется первый вызов.
Если все работает так, как я думаю, то, объявив интерфейс IClient как oneway
, я гарантирую, что это так. По крайней мере, я не могу придумать никакого способа, чтобы вызов из IServer.doSomething()
в IClient.reportBack()
мог немедленно вернуться (что oneway
должен гарантировать), но IClient.reportBack
все еще мог повторно вызвать IServer.doSomething
рекурсивно в том же потоке. Либо новый поток в IServer должен быть запущенным, или же старый поток IServer может быть повторно использован для внутреннего вызова IServer.doSomething (), но только после того, как внешний вызов IServer.doSomething()
вернулся.
oneway
.1 ответ:
Ключевое слово oneway означает, что если этот вызов приводит к IPC (то есть вызывающий и вызываемый находятся в разных процессах), то вызывающий процесс не будет ждать, пока вызываемый процесс обработает IPC. Если это не приводит к IPC (то есть они оба находятся в одном процессе), вызов будет синхронным. Это досадная деталь, которая значительно упрощает реализацию binder IPC. Если они находятся в одном процессе, то вызов является обычным вызовом метода java.