2012-09-27 25 views
37

Tôi đã xem qua cả hai khái niệm HandlersrunOnUiThread. Nhưng với tôi nó vẫn có vẻ là một nghi ngờ như trên mà sự kiện nào họ khác nhau chính xác.Tại sao sử dụng Trình xử lý trong khi runOnUiThread cũng giống vậy?

Cả hai đều có ý định thực hiện các tác vụ UI từ chuỗi nền. Nhưng các yếu tố sẽ được xem xét khi chúng tôi chọn trong số hai phương pháp.

Ví dụ: xem xét RunnableThread thực hiện dịch vụ web dưới nền và bây giờ tôi muốn cập nhật giao diện người dùng.

Cách tốt nhất để cập nhật giao diện người dùng của tôi là gì? Tôi có nên truy cập Handler hoặc runOnUiThread không?

Tôi vẫn biết mình có thể sử dụng số AsyncTask và sử dụng onPostExecute. Nhưng tôi chỉ muốn biết sự khác biệt.

+2

'runOnUiThread' chỉ là một phím tắt để đăng' Runnable' đến 'Handler'. 'Handler' là cơ sở của mỗi (?) Cơ sở giao tiếp luồng chéo được xác định bởi Android (ví dụ:' onPostExecute' của AsyncTask' sử dụng một 'Handler' để phân phối kết quả từ' doInBackground'). – zapl

Trả lời

63

Activity.runOnUiThread() là trường hợp đặc biệt chung chung hơn Handlers. Với Handler bạn có thể tạo truy vấn sự kiện của riêng mình trong chuỗi của riêng bạn. Sử dụng Handlers được khởi tạo với default constructorkhông có nghĩa là "mã sẽ chạy trên chuỗi giao diện người dùng" nói chung. Theo mặc định, trình xử lý được liên kết với Thread mà từ đó chúng được khởi tạo từ đó.

Để tạo Handler mà được đảm bảo liên kết với giao diện người dùng (chính) chủ đề bạn nên tạo Handler đối tượng binded đến chính Looper như thế này:

Handler mHandler = new Handler(Looper.getMainLooper()); 

Hơn nữa, nếu bạn kiểm tra việc thực hiện các runOnuiThread() phương pháp, nó được sử dụng Handler để làm những điều:

public final void runOnUiThread(Runnable action) { 
     if (Thread.currentThread() != mUiThread) { 
      mHandler.post(action); 
     } else { 
      action.run(); 
     } 
    } 

Như bạn có thể nhìn thấy từ đoạn mã trên, Runnable action sẽ exe bị cắt ngay lập tức, nếu runOnUiThread() được gọi từ chuỗi giao diện người dùng. Nếu không, nó sẽ đăng nó lên Handler, sẽ được thực hiện tại một số thời điểm sau đó.

+0

Nhưng không phải "Chủ đề mà từ đó chúng được khởi tạo từ". thường là chuỗi giao diện người dùng? –

+8

@ Giống như vậy, điều này hoàn toàn phụ thuộc vào mã của bạn. Thường thì có, các trình xử lý được khởi tạo từ luồng chính, nhưng có rất nhiều trường hợp nhà phát triển không có thông tin chính xác về luồng hiện tại khi tạo cá thể 'Handler'. Do đó, nhà phát triển nên sử dụng 'Trình xử lý mới (Looper.getMainLooper()) 'nếu anh ta cần sự bảo đảm mà trình xử lý sẽ thực hiện trong chuỗi chính. – HitOdessit

+0

hiểu điều đó rất hữu ích. –

0

Trình xử lý là cách cũ (API cấp 1) để thực hiện các công cụ, sau đó là AsycTask (API cấp 3), cùng với việc tập trung mạnh hơn vào việc sử dụng runOnUIThread (API cấp 1). Bạn nên tránh sử dụng trình xử lý càng nhiều càng tốt và thích hai trình xử lý khác tùy thuộc vào nhu cầu của bạn.

+1

Nhưng tại sao? Tôi cần sự khác biệt chính xác. Bạn có thể giải thích thêm được không. –

+0

Không có sự khác biệt, bạn có thể đạt được những điều tương tự với Handlers và Loopers, nhưng những kỹ thuật này giúp bạn tránh được những sai lầm. Xem http://en.wikipedia.org/wiki/Syntactic_sugar – Animesh

1

Trình xử lý có nhiều thao tác như thông báo qua và cập nhật giao diện người dùng thường xuyên nếu bạn bắt đầu Chủ đề cho bất kỳ thao tác nào .A Handler cho phép bạn gửi và xử lý các đối tượng Tin nhắn và Runnable được kết hợp với MessageQueue của chủ đề hữu ích trong nhiều ứng dụng như bluetooth trò chuyện ,, wifi trò chuyện ... và xử lý đã như Phương pháp PostDelay và PostAtTime mà bạn có thể chơi xung quanh bất kỳ điểm để animate và tầm nhìn thay đổi và vân vân

bạn phải tìm trong này

http://developer.android.com/guide/components/processes-and-threads.html

http://developer.android.com/tools/testing/activity_testing.html

+0

Vâng, nhưng tại sao không sử dụng runOnUIThread ở đây? –

+1

runOnUIThread luôn thực hiện tính toán trên chuỗi giao diện người dùng, trong khi Sử dụng Trình xử lý U có thể kích hoạt một Chủ đề để thực hiện tính toán nặng ở đó và đăng kết quả vào chuỗi giao diện người dùng Sử dụng Trình xử lý. Vì vậy, nếu u sử dụng runOnUIThread, sau đó hãy cẩn thận không làm tính toán nặng trên it.Async quá sử dụng Hanlder bên trong để đăng cập nhật và tiến bộ. nó tốt hơn phụ thuộc vào ur dễ sử dụng. –

1

Làm theo câu trả lời của HitOdessit.

Bạn có thể tạo một lớp như thế này.

public class Global{ 
    private static Handler mHandler = new Handler(Looper.getMainLooper()); 
    public static void runOnUiThread(Runnable action){ 
     mHandler.post(action); 
    } 
} 

Và sau đó gọi nó như thế này.

Global.runOnUiThread(new Runnable(){ 
    //Your code 
}); 

Và điều này có thể được chạy từ mọi nơi (nơi bạn có quyền truy cập vào lớp Toàn cầu).

0

Cách tốt nhất để cập nhật giao diện người dùng của tôi là gì? Tôi có nên đến Handler hoặc runOnUiThread không?

Nếu số điện thoại Runnable của bạn cần cập nhật giao diện người dùng, hãy đăng nó trên runOnUiThread.

Nhưng không phải lúc nào cũng có thể đăng Runnable trên Chủ đề giao diện người dùng.

Nghĩ về kịch bản, nơi bạn muốn thực hiện Hoạt động mạng/IO Hoặc gọi dịch vụ web. Trong trường hợp này, bạn không thể đăng Runnable vào Chủ đề giao diện người dùng. Nó sẽ ném android.os.NetworkOnMainThreadException

Đây là loại Runnable nên chạy trên các chủ đề khác nhau như HandlerThread. Sau khi hoàn thành hoạt động của bạn, bạn có thể đăng kết quả trở lại Giao diện người dùng bằng cách sử dụng Handler, đã được liên kết với Giao diện người dùng.

public void onClick(View view) { 

    // onClick on some UI control, perform Network or IO operation 

    /* Create HandlerThread to run Network or IO operations */ 
    HandlerThread handlerThread = new HandlerThread("NetworkOperation"); 
    handlerThread.start(); 

    /* Create a Handler for HandlerThread to post Runnable object */ 
    Handler requestHandler = new Handler(handlerThread.getLooper()); 

    /* Create one Handler on UI Thread to process message posted by different thread */ 

    final Handler responseHandler = new Handler(Looper.getMainLooper()) { 
     @Override 
     public void handleMessage(Message msg) { 
      //txtView.setText((String) msg.obj); 
      Toast.makeText(MainActivity.this, 
        "Runnable on HandlerThread is completed and got result:"+(String)msg.obj, 
        Toast.LENGTH_LONG) 
        .show(); 
     } 
    }; 

    NetworkRunnable r1 = new NetworkRunnable("http://www.google.com/",responseHandler); 
    NetworkRunnable r2 = new NetworkRunnable("http://in.rediff.com/",responseHandler); 
    requestHandler.post(r1); 
    requestHandler.post(r2); 

} 

class NetworkRunnable implements Runnable{ 
    String url; 
    Handler uiHandler; 

    public NetworkRunnable(String url,Handler uiHandler){ 
     this.url = url; 
     this.uiHandler=uiHandler; 
    } 
    public void run(){ 
     try { 
      Log.d("Runnable", "Before IO call"); 
      URL page = new URL(url); 
      StringBuffer text = new StringBuffer(); 
      HttpURLConnection conn = (HttpURLConnection) page.openConnection(); 
      conn.connect(); 
      InputStreamReader in = new InputStreamReader((InputStream) conn.getContent()); 
      BufferedReader buff = new BufferedReader(in); 
      String line; 
      while ((line = buff.readLine()) != null) { 
       text.append(line + "\n"); 
      } 
      Log.d("Runnable", "After IO call:"+ text.toString()); 

      Message msg = new Message(); 

      msg.obj = text.toString(); 

      /* Send result back to UI Thread Handler */ 
      uiHandler.sendMessage(msg); 


     } catch (Exception err) { 
      err.printStackTrace(); 
     } 
    } 
} 
Các vấn đề liên quan