2012-01-18 24 views
5

Có cách tiếp cận tốt để có một HandlerThread trong ứng dụng để thực hiện các hành động chi tiêu thời gian khác nhau, chẳng hạn như, sắp xếp hoặc thậm chí có thể làm việc với luồng web/tệp không? Điều gì là tốt hơn để sử dụng cho các mục đích như vậy: một số AsyncTask 's, một số Thread s hoặc một HandlerThread như http://hi-android.info/src/android/webkit/WebViewWorker.java.html ?Điều gì tốt hơn khi sử dụng một số AsyncTask hoặc HandlerThread (Chủ đề đường ống)?

+0

Từ kinh nghiệm của tôi - Tôi sử dụng AsyncTasks cho tất cả công việc cơ sở dữ liệu. Một điều tốt là, đạt đến postExecute() bạn biết rằng thread riêng biệt đã kết thúc. Đối với các tác vụ yêu cầu phải có thời gian dài (luồng/cập nhật từ web) - Trình xử lý hoặc mở rộng trực tiếp lớp Thread. – hovanessyan

+0

Tôi thích AsyncTask rất nhiều, nhưng đối với một số phiên bản của Android, nó cho phép nhiều luồng chạy song song thay vì tuần tự. Điều này có thể dẫn đến tất cả các loại tranh chấp xấu xí khi làm việc với cơ sở dữ liệu. Hãy cẩn thận ở ngoài đó. –

Trả lời

1

Câu trả lời ngắn gọn, tất cả đều tốt vì bạn không khóa giao diện người dùng.

Câu trả lời dài hơn, Chủ yếu là tùy chọn. Các giải pháp tôi sử dụng là một sự kết hợp của các chủ đề cơ bản và một xử lý. Vì một chuỗi cơ bản không chạy trên luồng giao diện người dùng chính, thường là khi hoàn tất, bạn cần phải báo cáo lại hoặc cập nhật cài đặt. Đây là khi tôi sử dụng một trình xử lý và một bộ các phím dễ đọc. Do đó cho phép tôi truy cập bất kỳ chế độ xem nào và thay đổi nó khi cần. Hãy nhớ rằng, nó là không khôn ngoan để khai báo và giữ tài liệu tham khảo toàn cầu để xem, phân bổ và sử dụng khi cần thiết và loại bỏ khi thực hiện.

private static final int SET_LOADING = 0; 
private static final int SET_TEXT  = 1; 


private Handler mEventHandler = new Handler() { 

    @Override 
    public void handleMessage(Message msg) { 
     // if stmts||switch - personal preference 
     if(msg.what  == SET_LOADING){ 

      setLoading(((Boolean) msg.obj)); 

     }else if(msg.what == SET_TEXT){ 

      setText(msg.arg1, (String) msg.obj); 

     } 
     super.handleMessage(msg); 
    } 
} 

/** 
* set the text of a textbox 
* @param id int - R.id.{...} 
* @param text String 
*/ 
private void setText(int id, String text){ 
    TextView t = ((TextView) findViewById(id)); 
    if(t != null){ 
     t.setText(text); 
    } 
} 


/** 
* is the UI currently loading something? lock controls 
* @param isLoading boolean 
*/ 
private void setLoading(boolean isLoading){ 
    mIsLoading = isLoading; 
    if(isLoading){ 
     (SomeSpinningProgressBar).setVisibility(View.VISIBLE); 
    }else{ 
     (SomeSpinningProgressBar).setVisibility(View.INVISIBLE); 
    } 
} 



public void onClick(View v) { 
    /** 
    * some button that triggers a database connection 
    */ 
    if(v.getId() == R.id.some_button) { 

     /** basic thread */ 
     new Thread(new Runnable() { 
       public void run() { 
        if(this.hasWebConnection()){ 
         /** tell the UI thread to start loading */ 
         mEventHandler.sendMessage(
          mEventHandler.obtainMessage(SET_LOADING, 0, 0, true)); 

         // do work... 

         if(someErrorOccuredBoolean){ 
          /** report to user of an error */ 
          mEventHandler.sendMessage(
           mEventHandler.obtainMessage(SET_TEXT, R.id.some_textview, 0, "There was an error!")); 
         } 
         /** tell the UI thread to stop loading */ 
         mEventHandler.sendMessage(
           mEventHandler.obtainMessage(SET_LOADING, 0, 0, false)); 
        }else{ 
         mEventHandler.obtainMessage(SET_TEXT, R.id.some_textview, 0, "No internet found!!")); 
        } 
       } 
      } 
     );  
    } 
} 
0

Đôi khi, đặc biệt khi bạn sử dụng thư viện gốc, bạn phải gọi các hàm trên cùng một chuỗi mà bạn đã dùng để khởi tạo thư viện. Lý do là thư viện có thể lưu trữ một thứ gì đó vào bộ nhớ cục bộ. Trong trường hợp này, AsyncTask không phải là một tùy chọn.

Thư viện hệ thống có sử dụng bộ nhớ cục bộ hay không và có sử dụng nó trong tương lai không ... Vâng, bạn thấy quan điểm của tôi: ở bên an toàn, khi tôi sử dụng thư viện JNI, tôi chỉ muốn sử dụng một chuỗi, có nghĩa là không có AsyncTask -ing. Bằng cách này, vì một đường ống dẫn (còn được gọi là một chuỗi xử lý) thực hiện một nhiệm vụ tại một thời điểm, tôi phải sử dụng các chuỗi xử lý khác nhau cho các tác vụ có thể chạy song song.

1

Bạn phải hoạt động tiêu tốn thời gian đại biểu (mạng, truy cập cơ sở dữ liệu, ...) cho một số loại chuỗi công việc. Không thể chấp nhận chặn luồng chính (UI).

AsyncTask là đối tượng cấp cao. Nó sẽ xử lý việc xử lý luồng và liên lạc liên ren cho bạn, sử dụng một số nội bộ HandlerExecutor. Nó đã được thiết kế cho (rất) trường hợp phổ biến của việc làm một cái gì đó trong nền và đẩy kết quả đến giao diện người dùng.

Sử dụng HandlerHandlerThread (hoặc sự kiện Thread) trực tiếp giúp bạn linh hoạt hơn, với chi phí của một mã phức tạp hơn, và một số cạm bẫy tinh tế (ví dụ How to Leak a Context: Handlers & Inner Classes).

Một lựa chọn bạn thực hiện là thực thi các tác vụ theo serially hoặc song song. A HandlerThread sẽ tuần tự hóa chúng. Đối với AsyncTask nó phụ thuộc vào phiên bản Android (nhưng điều này có thể được ghi đè). Tạo một Thread mỗi lần có thể dẫn đến quá nhiều luồng đồng thời.

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