Более эффективный способ обновить UI от Сервиса, чем намерения?

У меня в настоящее время есть Сервис в Android, который является демонстрационным клиентом VoIP, таким образом, он прекращает слушать для сообщений SIP и если он получает тот, он запускает экран Activity с компонентами UI.

Затем следующие сообщения SIP определяют то, что Действие должно отобразить на экране. Например, если входящий вызов это отобразит Ответ или Отклонение или исходящий вызов, это покажет экран набора номера.

В минуту я использую Намерения сообщить Действию, что указывает, что оно должно отобразиться.

Пример следующие:


        Intent i = new Intent();
        i.setAction(SIPEngine.SIP_TRYING_INTENT);
        i.putExtra("com.net.INCOMING", true);
        sendBroadcast(i);

        Intent x = new Intent();
        x.setAction(CallManager.SIP_INCOMING_CALL_INTENT);
        sendBroadcast(x);
        Log.d("INTENT SENT", "INTENT SENT INCOMING CALL AFTER PROCESSINVITE");

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

Пример кода следующим образом:


       SipCallListener = new BroadcastReceiver(){

            @Override
            public void onReceive(Context context, Intent intent) {
                    String action = intent.getAction(); 

                    if(SIPEngine.SIP_RINGING_INTENT.equals(action)){
                        Log.d("cda ", "Got RINGING action SIPENGINE");
                        ringingSetup();
                    }         

                    if(CallManager.SIP_INCOMING_CALL_INTENT.equals(action)){
                        Log.d("cda ", "Got PHONE RINGING action");
                        incomingCallSetup();
                    }  
            }
        };
        IntentFilter filter = new IntentFilter(CallManager.SIP_INCOMING_CALL_INTENT);
        filter.addAction(CallManager.SIP_RINGING_CALL_INTENT);
        registerReceiver(SipCallListener, filter);

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

Таким образом, я задавался вопросом, существует ли другой более эффективный и более чистый способ сделать это?

Существует ли способ сохранить Намерения широковещательно передать только в приложении?

Обратные вызовы были бы лучшей идеей? Раз так, почему и каким образом они должны быть реализованы?

41
задан Donal Rafferty 12 April 2010 в 11:03
поделиться

1 ответ

ОБНОВЛЕНИЕ 2015:

Этот вопрос / ответ все еще вызывает небольшую активность, но ему уже более 5 лет, и все немного изменилось. 5 лет назад ниже я отвечал, как бы я с этим справился. Позже я написал очень легкое решение для внедрения зависимостей, которое я использовал некоторое время (о котором я упоминал в комментариях). В настоящее время я бы ответил на этот вопрос с помощью Dagger и RxAndroid. Dagger для внедрения класса «посредника» как в Службу, так и во все Действия, о которых необходимо уведомлять, Служба будет отправлять обновление статуса в класс посредника, а класс посредника будет предоставлять наблюдаемый объект для действий, которые будут использовать обновление состояния ( вместо широковещательного приемника ОП).

Исходный ответ

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

РЕДАКТИРОВАТЬ:

В ответ на комментарий, вот более конкретная информация.

В настоящее время ваше приложение по большей части состоит из классов, производных от Activity, и классов, производных от сервиса. По сути, вы получаете функциональность от экземпляра класса android.app.Application. Это объявлено в вашем манифесте (по умолчанию) следующей строкой:

<application android:icon="@drawable/icon" android:label="@string/app_name">

Элемент приложения в вашем манифесте не использует атрибут android: name, поэтому он просто создает экземпляр класса android.app.Application по умолчанию для представляют глобальный контекст вашего приложения.

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

<application
    android:name="com.mycompany.myapp.app.ApplicationEx"
    android:icon="@drawable/app_icon"
    android:label="@string/app_name">

Теперь я могу добавить в ApplicationEx методы для действий и служб, которые будут использоваться для связи.Всегда существует единственный экземпляр вашего глобального контекста приложения, так что это ваша отправная точка, если что-то должно быть глобальным для вашего приложения.

Во-вторых, вместо того, чтобы получать свои услуги и действия из Service и Activity, я создаю подкласс каждого из них с помощью метода getAppContext, который приводит возвращаемое значение getApplicationContext (которое уже существует в обоих этих классах, потому что они унаследован от Context) в мой класс ApplicationEx.

Итак ........

Все, что было сказано, вы добавляете свойство CurrentActivity в свой класс ApplicationEx типа Activity (или ActivityBase, если вы подклассифицируете его, как я). В методе onResume ActivityBase вы передаете себя ApplicationEx, чтобы он установил CurrentActivity для этого действия. Теперь вы можете предоставлять методы в ApplicationEx для передачи информации непосредственно в текущее действие, вместо того, чтобы полагаться на механизмы Intent.

Это настолько ясно, насколько я могу это сказать

52
ответ дан 27 November 2019 в 00:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: