2011-11-13 38 views
9

Look, tôi có đoạn mã sau:Trình xử lý ảnh hưởng đến cách onReceiveResult (ResultReceiver) được gọi ra như thế nào?

Hành động của tôi:

final Intent intent = new Intent(getApplicationContext(), MyService.class) 
.putExtra(UploadService.EXTRA_RESULT_RECEIVER, new ResultReceiver(null) { 
      @Override 
      protected void onReceiveResult(int resultCode, Bundle resultData) { 
       super.onReceiveResult(resultCode, resultData); 
       String result = resultData.getString(MyService.EXTRA_RESULT_SUCCESS); 
       ... 
       imageView.setBackgroundDrawable(bitmap);// here my code fails 
      } 
     }) 

MyService:

Bundle b = new Bundle(); 
    b.putString(EXTRA_RESULT_SUCCESS, response.toString()); 
    resultReceiver.send(0, b); 

Và ứng dụng của tôi không thành công trên dòng "imageView.setBackgroundDrawable (bitmap)" như sau ngoại lệ:

11-13 16:25:38.986: ERROR/AndroidRuntime(3586): FATAL EXCEPTION: IntentService[MyService] 
    android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 

Nhưng doe này không xảy ra khi tôi xác định người nhận như thế này (với người xử lý):

new ResultReceiver(new Handler()){.../*here goes the same code as in the first example. nothing has been changed*/} 

So. Nó không thất bại khi tôi vượt qua một Trình xử lý mặc định. Và tôi yêu cầu Lý do tại sao? Trong cả hai cách mã của tôi được gọi, nhưng khi không có Trình xử lý nào được chỉ định thì nó không thành công. Handler có ảnh hưởng gì?

Trả lời

8

Các mối quan hệ Handler vào khuôn khổ Android và đảm bảo rằng bất kỳ mã được chạy trong callbacks của Handler được thực thi trên chủ đề Looper chính của Activity là nơi mà tất cả các callbacks vòng đời Activity và các cuộc gọi UI được thực hiện. Nếu bạn thực sự muốn hiểu nó hoạt động như thế nào bạn có thể đi lang thang qua nguồn trên Github, nhưng việc chạy mã trong một Handler được bảo đảm khá nhiều để đưa mọi thứ vào đúng chỗ.

+0

Tôi có một nghi ngờ. Có phải ResultReceiver.onReceiveResult đó sẽ luôn chạy trên chuỗi không phải là UI không? –

+0

Không, đó là việc sử dụng Trình xử lý đảm bảo rằng nó sẽ chạy đúng chuỗi. Thông thường không đảm bảo được thực hiện như là chủ đề mà người nhận sẽ được gọi là trên. – Femi

+0

OK! Nó dựa trên thread gọi trình thu kết quả. Cảm ơn bạn đã trả lời nhanh. –

3

Vấn đề là do imageView.setBackgroundDrawable() được gọi từ chuỗi dịch vụ của bạn. Điều này là không chính xác. Bạn cần đảm bảo rằng mọi cập nhật giao diện người dùng được thực hiện từ chuỗi giao diện người dùng.

Thật khó để giải thích chính xác những gì cần phải thay đổi từ các đoạn mã bạn cung cấp.

Android cung cấp một số kỹ thuật để cho phép các chủ đề không phải UI tương tác với các thành phần giao diện người dùng (và lớp Trình xử lý một trong các tùy chọn). IMHO, đây là một trong những khái niệm quan trọng nhất để có được quyền nếu bạn muốn phát triển các ứng dụng Android tốt.

Một số liên kết hữu ích:

http://developer.android.com/resources/articles/painless-threading.html

What is the Android UiThread (UI thread)

http://www.vogella.de/articles/AndroidPerformance/article.html

+1

Yeah, tôi thấy vấn đề điều đó xảy ra vì giao diện người dùng cập nhật đã được thực hiện từ thread khác. Nhưng điều này không xảy ra khi tôi vượt qua Trình xử lý mặc định. Vì vậy, khi tôi vượt qua nó, nó làm cho tất cả mọi thứ từ một chủ đề giao diện người dùng thay vì tạo ra một cái mới? Cảm ơn các liên kết, trông giống như một bài đọc thú vị! –

0

Tác phẩm sau đây dành cho tôi. Bạn có thể chạy bản cập nhật bitmap trong cùng một chuỗi hoạt động giao diện người dùng của mình bằng phương thức "runOnUiThread". Bạn nên xác định các lớp sau khi lớp bên trong của hoạt động giao diện người dùng của bạn:

class UpdateUI implements Runnable 
{ 
    Bitmap newBitmap; 

    public UpdateUI(Bitmap newBitmap) { 
     this.newBitmap = newBitmap; 
    } 
    public void run() { 
     imageView.setBackgroundDrawable(newBitmap); 
    } 
} 

Sau đó, trong resultReceiver của bạn:

@Override 
protected void onReceiveResult(int resultCode, Bundle resultData) { 
    // after get your bitmap 
    runOnUiThread(new UpdateUI(receivedBitmap)); 
    ... 
} 
Các vấn đề liên quan