2009-07-21 4 views
29

나는 A라는 액티비티를 가지고 있으며, 메뉴 항목 0을 선택하면 서비스 B가 생성되어 새로운 스레드에서 실행 가능한 C가 시작됩니다. 나는 내가 텍스트 뷰를 공개 정적 필드을 시도했습니다스폰 된 백그라운드 서비스에서 원래 활동의보기에 액세스하는 방법

스레드 C.에 액세스하려는 활동가있는 텍스트 뷰를 가지고 있지만, 다음과 같은 오류 발생 :

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) 

나는 또한이를 뷰를 의도를 통해 전달하려는 것으로 간주되지만 어떻게 작동하는지 알 수 없습니다. 이 작업을하려면 무엇이 필요합니까?

답변

21

위젯을 GUI 스레드 (일명 '뷰 계층을 생성 한 스레드')에서 업데이트해야합니다. 이 작업을 수행하는 표준 방법은 Handler을 사용하고 처리기 사용 방법의 예는 ProgressDialog Example에서 찾을 수 있습니다 ('두 번째 스레드가있는 ProgressDialog보기'펼치기).

1

다른 방법은 os.android.AsyncTask을 처리하는 것입니다.

2

정말 서비스에서 위젯을 직접 조작하고 싶지는 않습니다.

예를 들어 사용자가 G1의 키보드를 슬라이드 아웃한다고 가정합니다. 귀하의 활동은 파괴되고 재창조됩니다. 그러나 귀하의 서비스는 현재 없어진 활동에서 위젯을 잡고 있습니다. 기껏해야 업데이트가 발생하지 않습니다. 최악의 경우 업데이트로 인해 충돌이 발생하거나 응용 프로그램이 가비지 수집을 할 수 없기 때문에 메모리 누수가 발생합니다.

서비스 알림 활동이있는 경우 서비스가 정상적으로 격리되어 있으면 활동이 파괴되었을 때 활동이 서비스에서 분리됩니다.

25

ListView가 별도의 스레드에서 오는 웹 서비스 응답에서 업데이트해야하는 비슷한 문제가있었습니다.

similar question & example을 분석 한 후, 여기 당신을 위해 작동해야 솔루션입니다 :

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(); 
} 
+2

코드 예제는 항상 훨씬 더 유용한 설명보다. 감사합니다 :) – HXCaine

+0

감사합니다,이 문제는 오랫동안 나를 따라왔다! 고맙습니다! – Daniel

관련 문제