Android: Làm cách nào để tôi có thể chuyển các tham số cho onPreExecute () của AsyncTask?


116

Tôi sử dụng một AsyncTaskđể tải các hoạt động mà tôi đã triển khai như một lớp bên trong.

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

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

Cách giải quyết rõ ràng có thể là tạo một 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 lắm. Có cách nào tốt hơn để làm điều này?

Câu trả lời:


231

Bạn có thể ghi đè hàm tạo. 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 tác vụ, hãy thực hiện một số việc như:

new MyAsyncTask(true).execute(maybe_other_params);

Chỉnh sửa: điều này hữu ích hơn việc tạo biến thành viên vì nó đơn giản hóa việc gọi tác vụ. So sánh đoạn mã trên với:

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

3
Đây là khá 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 chứ không phải lớp bên ngoài nếu đó là ý bạn. Đây là những gì tôi đã làm: lớp private MyAsyncTask mở rộng AsyncTask <Void, Void, Void> {private boolean showLoading; public MyAsyncTask (boolean showLoading) {super (); this.showLoading = showLoading; // làm công cụ} void onPreExecute () {if (showLoading) {// ...}} // doInBackground () et al. }
Steven Meliopoulos

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

1
Bạn không thực sự cần super () trong hàm tạo AsynkTask.
ostergaard

62

1) Đối với tôi đó là cách đơn giản nhất để chuyển các tham số cho tác vụ không đồng bộ là như thế này

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

Khai báo và sử dụng tác vụ async như tại đâ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) Truyền các phương thức cho tác vụ không đồng bộ Để tránh phải mã hóa cơ sở hạ tầng không đồng bộ-Tác vụ (luồng, bộ xử lý dữ liệu, ...) nhiều lần, bạn có thể cân nhắc chuyển các phương thức sẽ được thực thi trong tác vụ không đồng bộ của mình dưới dạng tham số. Ví dụ sau đây phác thảo 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ụ không đồng bộ để 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;
        }
    });     
}

11

tại sao, như thế nào và những tham số nào được truyền cho Asynctask <>, xem chi tiết tại đây . 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 tác vụ không đồng bộ được xác định bởi 3 kiểu chung, được gọi là Tham số, Tiến trình và Kết quả, và 4 bước, được gọi là onPreExecute, doInBackground, onProgressUpdate và onPostExecute.

Các loại chung của AsyncTask:

Ba loại được sử dụng bởi một tác vụ không đồng bộ là:

Tham số, loại tham số được gửi đến tác vụ khi thực thi. Tiến độ, loại đơn vị tiến độ đượ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 một tác vụ không đồng bộ. Để đánh dấu một loại là không sử dụng, chỉ cần sử dụng loại Void:

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

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

Hoặc Bạn có thể rõ vai trò của AsyncTask là gì bằng cách tham khảo Blog của Sankar-Ganesh

Cấu trúc của một 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 thi trước khi bắt đầu Thread mới. Không có giá trị đầu vào / đầu ra, vì vậy chỉ cần khởi tạo các biến hoặc bất cứ điều gì bạn nghĩ mình cần làm.

protected Z doInBackground(X...x){

}

Phương thức 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 chuỗi khác với chuỗi chính. Ở đây chúng ta có một 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ó “... expand AsyncTask” Đây là các LOẠI tham số đầu vào) và trả về một đối tượng từ kiểu "Z".

được bảo vệ void onProgressUpdate (Y y) {

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

void bảo vệ onPostExecute (Z z) {

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

Còn 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 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 kiểu X.

Khi nhiệm vụ của mình đang chạy, chúng ta có thể tìm hiểu trạng thái 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.

PENDING - Cho biết tác vụ chưa được thực hiện.

FINISHED - Cho biết onPostExecute (Z) đã kết thúc.

Gợi ý về cách sử dụng AsyncTask

Không gọi các phương thức onPreExecute, doInBackground và onPostExecute theo cách thủ công. Việc này do hệ thống tự động thực hiện.

Bạn không thể gọi AsyncTask bên trong AsyncTask hoặc Thread khác. Việc gọi phương thức thực thi phải được thực hiện trong Chuỗi giao diện người dùng.

Phương thức onPostExecute được thực thi trong Chuỗi giao diện người dùng (ở đâ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, bằng cách này, bạn có thể đặt bất kỳ đối tượng và kiểu nào bạn muốn.


4

Bạn có thể truyền tham số trong hàm tạo tác vụ hoặc khi bạn gọi thực thi:

AsyncTask<Object, Void, MyTaskResult>

Tham số đầu tiên (Đối tượng) được truyền trong 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 làm (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);

        }
    }

}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.