Подтвердить что ты не робот

Как получить доступ к исходным представлениям активности из службы порожденного фона

У меня есть действие под названием A, и при выборе пункта меню 0 он запускает службу B, которая запускает runnable C в новом потоке. У меня есть TextView в действии A, к которому я хочу получить доступ в потоке C.

Я попытался сделать TextView общедоступным статическим полем, но это порождает следующую ошибку:

07-21 07:26:25.723: ERROR/AndroidRuntime(1975): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
07-21 07:26:25.723: ERROR/AndroidRuntime(1975):     at android.view.ViewRoot.checkThread(ViewRoot.java:2440)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975):     at android.view.ViewRoot.invalidateChild(ViewRoot.java:522)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975):     at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:540)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975):     at android.view.ViewGroup.invalidateChild(ViewGroup.java:2332)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975):     at android.view.View.invalidate(View.java:4437)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975):     at android.widget.TextView.updateAfterEdit(TextView.java:4593)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975):     at android.widget.TextView.handleTextChanged(TextView.java:5932)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975):     at android.widget.TextView$ChangeWatcher.onTextChanged(TextView.java:6081)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975):     at android.text.SpannableStringBuilder.sendTextChange(SpannableStringBuilder.java:889)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975):     at android.text.SpannableStringBuilder.change(SpannableStringBuilder.java:352)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975):     at android.text.SpannableStringBuilder.change(SpannableStringBuilder.java:269)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975):     at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:432)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975):     at android.text.SpannableStringBuilder.append(SpannableStringBuilder.java:259)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975):     at android.text.SpannableStringBuilder.append(SpannableStringBuilder.java:28)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975):     at android.widget.TextView.append(TextView.java:2191)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975):     at android.widget.TextView.append(TextView.java:2178)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975):     at com.android.peekaboo.DoScan$scanBody.run(DoScan.java:36)
07-21 07:26:25.723: ERROR/AndroidRuntime(1975):     at java.lang.Thread.run(Thread.java:1058)

Я также рассматривал попытку передать представление через намерение, но не знаю, как это будет работать. Что мне нужно, чтобы сделать эту работу?

4b9b3361

Ответ 1

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

Ответ 2

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

После анализа подобного вопроса и пример, вот решение, которое должен работать для вас:

public class A extends Activity implements Callback {

     callserviceB () { } // where your service B being called;

     @Override
     public void returnServiceResponse() {
          workOnResponse();
          handler.sendEmptyMessage(0);
     }

     private Handler handler = new Handler() {
          public void  handleMessage(Message msg) {
               //update your view from here only.
          }
     }
}

public class B implements Runnable {
     Callback callback;

     public void run() {
         //your business logic.
         callback.returnServiceResponse();
     }
}

public interface Callback {
     public void returnServiceResponse();
}

Ответ 3

Вы действительно не хотите напрямую манипулировать виджетами из службы.

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

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

Ответ 4

Другим способом является использование os.android.AsyncTask для обработки.