2015-03-06 30 views
12

Hãy xem xét đoạn mã sau:Điều gì sẽ xảy ra nếu một Trình xử lý gửi một thông điệp đến một luồng sau Looper.prepare() nhưng trước khi Looper.loop() được gọi?

Looper.prepare(); 
handler = new Handler() { 
     @Override 
     public void handleMessage(Message msg) { 
      super.handleMessage(msg); 
      getLooper().quitSafely(); 
     } 
    }; 
for(int i = 0; i < urls.size(); i++) { 
    useCaseProvider.get().execute(callback, handler, urls.get(i), threadPool); 
} 
Looper.loop(); 

//Continue processing the results of all the use cases after the  
//loop has been asked to terminated via the handler 

Một nền chút: Tôi đang làm một số xử lý trên thread UI nơi tôi sẽ cần phải ping một lớn về thiết bị và làm điều gì đó với kết quả. Tôi cần phải thực hiện các yêu cầu song song để có hiệu quả.

Câu hỏi: Nếu một trong các trường hợp sử dụng bằng cách nào đó thực hiện đủ nhanh và thực hiện cuộc gọi lại trước khi tôi có thể nhấn Looper.loop(); tin nhắn sẽ được xếp hàng đợi hoặc bị mất? Các cuộc gọi lại đang được đăng lại cho chủ đề này bởi trình xử lý gửi một chuỗi chạy đến chuỗi ban đầu.

Trả lời

7

Giả sử bạn đã gọi Looper.prepare() trước khi useCaseProvider của bạn cung cấp kết quả, bạn sẽ ổn. Nếu Looper.prepare không được gọi là bạn sẽ thấy RuntimeException bị ném.

Đối tượng Looper được gắn với một chuỗi cục bộ lưu trữ hàng đợi thư. Hàm Looper.prepare sẽ xây dựng hàng đợi thông điệp này tại thời điểm bạn có thể bắt đầu xếp hàng các thông báo. Khi bạn kích hoạt Looper.loop() thì khi các thông báo đang chờ xử lý đó sẽ bắt đầu thực thi.

Nhìn vào đoạn mã, tôi không quá chắc chắn cách mọi thứ được gắn với nhau. Nói chung, bạn muốn xây dựng một looper như thế này:

private static final class MyThread extends Thread { 
    private Handler mHandler; 

    @Override 
    public void run() { 
     Looper.prepare(); 

     mHandler = new Handler() { 
      @Override 
      public void handleMessage(Message msg) { 
       // handle message 
      } 
     }; 

     Looper.loop(); 
    } 

    public Handler getHandler() { 
     return mHandler; 
    } 
} 

tôi giả hồ bơi thread của bạn là sau đó một thread pool MyThread, mỗi trong số đó có Looper riêng của họ. Các hồ bơi thread nên khởi tạo chủ đề của bạn vì vậy một khi bạn cung cấp một Runnable được thực hiện bởi chủ đề của bạn, các run() phương pháp nên có Looper khởi tạo. Mặt khác, nếu bạn muốn liên kết Trình xử lý của bạn với một looper cụ thể (nghĩa là bạn không xây dựng Trình xử lý trong một chuỗi như trên) thì bạn nên chuyển chuỗi Looper vào hàm tạo như:

Handler h = new Handler(myLooperThread); 

Nếu bạn không chỉ định điều đó, thì trình xử lý sẽ sử dụng chuỗi mà nó được tạo để lấy Looper của chủ đề đó từ đối tượng ThreadLocal.

Cuối cùng, nếu ý định của bạn là có thư được phân phối trên Trình xử lý được liên kết với chuỗi giao diện người dùng thì bạn không nên lo lắng về việc gọi Looper.prepare hoặc Looper.loop. Điều này được xử lý bởi Activity.

+0

Vì vậy, về cơ bản trong đoạn trích xử lý thư của mình trên 'MessageQueue' sẽ bị trì hoãn bởi thời gian thực hiện của vòng lặp' for'. – Emmanuel

+0

Khá nhiều. Bất kỳ nỗ lực để cung cấp cho một Looper uninitialized sẽ dẫn đến một ngoại lệ thời gian chạy. Tùy thuộc vào những gì cần thiết, một IntentService có thể là một cách tốt hơn để đi. – jagsaund

Các vấn đề liên quan