Android - sendBroadcast () и onReceive () - синхронное решение для межпроцессного взаимодействия - PullRequest
2 голосов
/ 27 января 2012

Я хотел бы создать библиотеку, которая бы выполняла некоторые намерения отправлять / получать информацию синхронно (со стороны клиента).Так что клиенту моей библиотеки не придется заботиться о реализации получателей.

Библиотека отправит куда-нибудь намерение и получит ответ.Затем он будет возвращать результат клиенту синхронно.

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

Предлагаемое решение (упрощенно!).Библиотека:

public class Helper {
private Context context;
private BroadcastReceiver tempReceiver;
private int result = 0;

int getResult() {

    tempReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Helper.this.result = 1;
        }
    };
    context.registerReceiver(tempReceiver);
    context.sendBroadcast(/* ask for smth */);

    Thread.sleep(5000);

    context.unregisterReceiver(tempReceiver);
    return result; 
}
}

Клиент - это приложение, которое хочет получить некоторые данные из библиотеки, например:

int timeout = 5000;
Helper lib = new Helper(timeout);
lib.getData();

Что вы думаете об этом?Какие угрозы?Я понимаю, что вызов getReturn () будет блокировать и не может быть вызван в потоке GUI.Вопрос, является ли решение для сна приемлемым.

Ответы [ 3 ]

2 голосов
/ 27 января 2012

Я полагаю, что вы уже знаете о стандартных синхронных и асинхронных компромиссах и ситуациях, когда они выгодны, а не так.

ИМО, ваш подход приемлем только в том случае, если трансляция также отправлена ​​вашим собственным приложением. Если вас интересует системная трансляция, то 5-секундная задержка может варьироваться между допустимой и катастрофической. Представьте себе, что вы регистрируетесь для трансляции «сфотографировано», а затем через 5 секунд, когда пользователь делает еще одну фотографию, ваш синхронный вызов возвращается, и вы отображаете что-то, что раздражает пользователя без конца.

Кроме того, как вы предлагаете иметь дело со случаями, когда Трансляция не носит разовый, а скорее непрерывный характер?

Я пытался разработать API, используя AsyncTask под одеялом; и разоблачить это синхронно. Но оказалось, что использование этого API будет намного более запутанным для клиентского кода. Я пришел к выводу, что некоторые вещи просто не должны выполняться синхронно; и продолжил с основанным на обратном вызове асинхронным подходом. Я хочу подчеркнуть, что трансляции не должны быть синхронными.

Только мои 2 цента.

1 голос
/ 27 января 2012

Я не понимаю, чего именно вы пытаетесь достичь.
Кто вещатель? Кто получатель? Было бы полезно лучше описать связь между библиотекой и клиентским кодом.

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

Синхронизация по спящим швам, как действительно неправильное проектное решение, и это не то, для чего следует использовать трансляции.

Если вам нужен синхронный обратный вызов, я бы порекомендовал шаблон слушателя, как это делает android: например, Интерфейс onClick.

0 голосов
/ 17 апреля 2017

основы! - синхронизация

public abstract class WorkerThread {

    @Override
    public void run()  {
        // loop 
        while(!isCanceled()) {
            try {
                //  wait() 
                waitUntilResumed():
                // when notified do work 
                doWork():
            } catch (InterruptedException e) {
              // restore interrupted state 
            }
        }
    }

    /**
     * main thread loop
     */
    protected abstract void doWork() throws InterruptedException;

    /**
     * blocks current thread until it is resumed
     */
    private synchronized void waitUntilResumed() throws InterruptedException {
        while (isPaused()) {
            wait();
        }
    }

    /**
     * resume thread 
     */
    public synchronized void resumeAction() {
        notifyAll();
    }

}  
...