2010-06-19 27 views
96

Tôi sử dụng AsyncTask để tải các hoạt động mà tôi đã triển khai làm lớp bên trong.Android: Làm cách nào tôi có thể chuyển các tham số cho OnPreExecute() của AsyncTask?

Trong onPreExecute() Tôi hiển thị hộp thoại tải mà sau đó tôi ẩn lại trong onPostExecute(). Nhưng đối với một số hoạt động tải tôi biết trước rằng họ sẽ kết thúc rất nhanh chóng vì vậy tôi không muốn hiển thị hộp thoại tải.

Tôi muốn biểu thị điều này bằng thông số boolean mà tôi có thể chuyển đến onPreExecute() nhưng rõ ràng vì một lý do nào đó onPreExecute() không nhận bất kỳ thông số nào.

Cách giải quyết rõ ràng có thể là tạo trường thành viên trong AsyncTask của tôi hoặc trong lớp bên ngoài mà tôi sẽ phải đặt trước mỗi thao tác tải nhưng điều đó có vẻ không thanh lịch. Có cách nào tốt hơn để làm điều này?

Trả lời

202

Bạn có thể ghi đè lên hàm tạo. Một cái gì đó như:

private class MyAsyncTask extends AsyncTask<Void, Void, Void> { 

    public MyAsyncTask(boolean showLoading) { 
     super(); 
     // do stuff 
    } 

    // doInBackground() et al. 
} 

Sau đó, khi gọi các nhiệm vụ, làm một cái gì đó như:

new MyAsyncTask(true).execute(maybe_other_params); 

Edit: này là có ích hơn việc tạo ra các biến thành viên bởi vì nó đơn giản hoá gọi nhiệm vụ. Hãy so sánh các mã trên với:

MyAsyncTask task = new MyAsyncTask(); 
task.showLoading = false; 
task.execute(); 
+3

Điều này hoàn toàn chính xác những gì tôi đã làm bây giờ. Tôi vẫn cần một biến thành viên nhưng trong AsyncTask và không phải là lớp bên ngoài nếu đó là những gì bạn có ý nghĩa. Đây là những gì tôi đã làm: lớp riêng MyAsyncTask mở rộng AsyncTask { riêng boolean showLoading; công khai MyAsyncTask (boolean showLoading) { super(); this.showLoading = showLoading; // do stuff } protected void onPreExecute() { if (showLoading) {// ... }} // doInBackground() et al. } –

+1

Yup, đó là khá nhiều ý tưởng :) – Felix

+3

Đây là câu trả lời đúng –

49

1) Đối với tôi đó là các thông số cách đi qua đơn giản nhất để async nhiệm vụ là như

// To call the async task do it like this 
Boolean[] myTaskParams = { true, true, true }; 
myAsyncTask = new myAsyncTask().execute(myTaskParams); 

Declare này và sử dụng nhiệm vụ async như đây

private class myAsyncTask extends AsyncTask<Boolean, Void, Void> { 

    @Override 
    protected Void doInBackground(Boolean...pParams) 
    { 
     Boolean param1, param2, param3; 

     // 

      param1=pParams[0];  
      param2=pParams[1]; 
      param3=pParams[2];  
     .... 
}       

2) Phương thức chuyển thành async-task Để tránh mã hóa cơ sở hạ tầng async-Task (thread, messagenhandler, ...) nhiều lần bạn có thể xem xét để chuyển các phương thức cần được thực hiện trong tác vụ async của bạn làm tham số. Ví dụ sau vạch ra cách tiếp cận này. Ngoài ra, bạn có thể cần phải phân lớp nhiệm vụ async để chuyển các tham số khởi tạo trong hàm tạo.

/* Generic Async Task */ 
interface MyGenericMethod { 
    int execute(String param); 
} 

protected class testtask extends AsyncTask<MyGenericMethod, Void, Void> 
{ 
    public String mParam;       // member variable to parameterize the function 
    @Override 
    protected Void doInBackground(MyGenericMethod... params) { 
     // do something here 
     params[0].execute("Myparameter"); 
     return null; 
    }  
} 

// to start the asynctask do something like that 
public void startAsyncTask() 
{ 
    // 
    AsyncTask<MyGenericMethod, Void, Void> mytest = new testtask().execute(new MyGenericMethod() { 
     public int execute(String param) { 
      //body 
      return 1; 
     } 
    });  
} 
8

tại sao, như thế nào và trong đó các tham số được truyền cho AsyncTask <>, xem chi tiết here. Tôi nghĩ đó là lời giải thích tốt nhất.

Tài liệu Android của Google nói rằng:

Một nhiệm vụ không đồng bộ được xác định bởi 3 loại chung chung, gọi là Params, Tiến độ và kết quả, và 4 bước, gọi onPreExecute, doInBackground, onProgressUpdate và onPostExecute.

kiểu generic AsyncTask của:

Ba loại được sử dụng bởi một nhiệm vụ không đồng bộ như sau:

Params, loại các thông số gửi đến nhiệm vụ khi thực hiện. Tiến trình, loại đơn vị tiến trình được xuất bản trong quá trình tính toán nền. Kết quả, loại kết quả của tính toán nền. Không phải tất cả các loại luôn được sử dụng bởi tác vụ không đồng bộ. Để đánh dấu một kiểu như là không sử dụng, bạn chỉ cần sử dụng các loại Void:

private class MyTask extends AsyncTask<Void, Void, Void> { ... } 

Bạn thêm có thể tham khảo: http://developer.android.com/reference/android/os/AsyncTask.html

Hoặc bạn có thể xóa whats vai trò của AsyncTask bởi đề cập Blog Sankar-Ganesh của

Vâng Cấu trúc của lớp AsyncTask điển hình như sau:

private class MyTask extends AsyncTask<X, Y, Z> 

    protected void onPreExecute(){ 

    } 

Phương thức này được thực hiện trước khi bắt đầu chuỗi mới. Không có giá trị đầu vào/đầu ra, do đó, chỉ cần khởi tạo biến hoặc bất cứ điều gì bạn nghĩ rằng bạn cần phải làm.

protected Z doInBackground(X...x){ 

} 

Phương pháp quan trọng nhất trong lớp AsyncTask. Bạn phải đặt ở đây tất cả những thứ bạn muốn làm trong nền, trong một chủ đề khác với chủ đề chính. Ở đây chúng ta có giá trị đầu vào là một mảng các đối tượng từ kiểu “X” (Bạn có thấy trong tiêu đề không? Chúng ta có “... mở rộng AsyncTask” Đây là các LOẠI của các tham số đầu vào) và trả về một đối tượng từ kiểu “Z”.

protected void onProgressUpdate (Y y) {

} Phương pháp này được gọi là sử dụng publishProgress phương pháp (y) và nó thường được sử dụng khi bạn muốn hiển thị bất kỳ tiến bộ hoặc thông tin trong màn hình chính, giống như một thanh tiến trình hiển thị tiến độ của thao tác bạn đang làm trong nền.

protected void onPostExecute (Z z) {

} Phương pháp này được gọi là sau khi hoạt động ở chế độ nền được thực hiện. Là một tham số đầu vào, bạn sẽ nhận được thông số đầu ra của phương thức doInBackground.

Còn các loại X, Y và Z thì sao?

Như bạn có thể suy ra từ cấu trúc trên:

X – The type of the input variables value you want to set to the background process. This can be an array of objects. 

Y – The type of the objects you are going to enter in the onProgressUpdate method. 

Z – The type of the result from the operations you have done in the background process. 

Làm thế nào để chúng ta gọi là nhiệm vụ này từ một lớp bên ngoài? Chỉ với hai dòng sau:

MyTask myTask = new MyTask(); 

myTask.execute(x); 

Trong đó x là tham số đầu vào của các loại X.

Một khi chúng ta có nhiệm vụ chạy của chúng tôi, chúng tôi có thể tìm hiểu tình trạng của nó từ “bên ngoài”. Sử dụng phương thức “getStatus()”.

myTask.getStatus(); và chúng tôi có thể nhận được trạng thái sau:

RUNNING - Cho biết tác vụ đang chạy.

ĐANG CHỜ - Cho biết tác vụ chưa được thực thi.

HOÀN THÀNH - Cho biết rằng onPostExecute (Z) đã hoàn tất.

gợi ý về việc sử dụng AsyncTask

Đừng gọi các phương pháp onPreExecute, doInBackground và onPostExecute bằng tay. Việc này được hệ thống tự động thực hiện.

Bạn không thể gọi AsyncTask bên trong AsyncTask hoặc Chủ đề khác. Cuộc gọi của phương thức thực hiện phải được thực hiện trong Thread UI.

Phương thức onPostExecute được thực thi trong Chủ đề giao diện người dùng (tại đây bạn có thể gọi một AsyncTask khác!).

Các tham số đầu vào của tác vụ có thể là một mảng Đối tượng, theo cách này bạn có thể đặt bất kỳ đối tượng và loại nào bạn muốn.

0

Bạn có thể vượt qua các tham số trong các nhà xây dựng nhiệm vụ hoặc khi bạn gọi thực hiện:

AsyncTask<Object, Void, MyTaskResult> 

Tham số đầu tiên (Object) được thông qua tại doInBackground. Tham số thứ ba (MyTaskResult) được trả về bởi doInBackground. Bạn có thể thay đổi chúng thành các loại bạn muốn. Ba dấu chấm có nghĩa là không hoặc nhiều đối tượng (hoặc một mảng trong số chúng) có thể được chuyển thành (các) đối số.

public class MyActivity extends AppCompatActivity { 

    TextView textView1; 
    TextView textView2; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main2);  
     textView1 = (TextView) findViewById(R.id.textView1); 
     textView2 = (TextView) findViewById(R.id.textView2); 

     String input1 = "test"; 
     boolean input2 = true; 
     int input3 = 100; 
     long input4 = 100000000; 

     new MyTask(input3, input4).execute(input1, input2); 
    } 

    private class MyTaskResult { 
     String text1; 
     String text2; 
    } 

    private class MyTask extends AsyncTask<Object, Void, MyTaskResult> { 
     private String val1; 
     private boolean val2; 
     private int val3; 
     private long val4; 


     public MyTask(int in3, long in4) { 
      this.val3 = in3; 
      this.val4 = in4; 

      // Do something ... 
     } 

     protected void onPreExecute() { 
      // Do something ... 
     } 

     @Override 
     protected MyTaskResult doInBackground(Object... params) { 
      MyTaskResult res = new MyTaskResult(); 
      val1 = (String) params[0]; 
      val2 = (boolean) params[1]; 

      //Do some lengthy operation  
      res.text1 = RunProc1(val1); 
      res.text2 = RunProc2(val2); 

      return res; 
     } 

     @Override 
     protected void onPostExecute(MyTaskResult res) { 
      textView1.setText(res.text1); 
      textView2.setText(res.text2); 

     } 
    } 

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