Android: ฉันจะส่งพารามิเตอร์ไปยัง onPreExecute () ของ AsyncTask ได้อย่างไร


116

ฉันใช้AsyncTaskสำหรับการโหลดการดำเนินการที่ฉันใช้เป็นคลาสภายใน

ในผมแสดงโต้ตอบโหลดซึ่งผมก็ซ่อนอีกครั้งในonPreExecute() onPostExecute()แต่สำหรับการโหลดบางอย่างฉันรู้ล่วงหน้าว่ามันจะเสร็จเร็วมากดังนั้นฉันจึงไม่ต้องการแสดงกล่องโต้ตอบการโหลด

ฉันต้องการระบุสิ่งนี้ด้วยพารามิเตอร์บูลีนที่ฉันสามารถส่งผ่านไปได้onPreExecute()แต่ดูเหมือนว่าด้วยเหตุผลบางประการonPreExecute()ไม่ได้ใช้พารามิเตอร์ใด ๆ

วิธีแก้ปัญหาที่ชัดเจนอาจเป็นการสร้างเขตข้อมูลสมาชิกใน AsyncTask ของฉันหรือในชั้นนอกซึ่งฉันจะต้องตั้งค่าก่อนการดำเนินการโหลดทุกครั้ง แต่ดูเหมือนจะไม่สวยหรูมากนัก มีวิธีที่ดีกว่านี้หรือไม่?

คำตอบ:


230

คุณสามารถแทนที่ตัวสร้าง สิ่งที่ต้องการ:

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

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

    // doInBackground() et al.
}

จากนั้นเมื่อเรียกงานให้ทำสิ่งต่อไปนี้

new MyAsyncTask(true).execute(maybe_other_params);

แก้ไข:สิ่งนี้มีประโยชน์มากกว่าการสร้างตัวแปรสมาชิกเนื่องจากช่วยลดความยุ่งยากในการเรียกใช้งาน เปรียบเทียบโค้ดด้านบนกับ:

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

3
นี่เป็นสิ่งที่ฉันทำไปแล้ว ฉันยังต้องการตัวแปรสมาชิก แต่อยู่ใน AsyncTask ไม่ใช่คลาสนอกถ้านั่นคือสิ่งที่คุณหมายถึง นี่คือสิ่งที่ฉันทำ: MyAsyncTask คลาสส่วนตัวขยาย AsyncTask <Void, Void, Void> {private boolean showLoading; MyAsyncTask สาธารณะ (บูลีน showLoading) {super (); this.showLoading = showLoading; // do stuff} มีการป้องกันโมฆะ onPreExecute () {if (showLoading) {// ... }} // doInBackground () et al. }
Steven Meliopoulos

1
ใช่นั่นเป็นความคิดที่ดีมาก :)
เฟลิกซ์

1
คุณไม่จำเป็นต้องใช้ super () ในตัวสร้าง AsynkTask
ostergaard

62

1) สำหรับฉันนั่นเป็นวิธีที่ง่ายที่สุดในการส่งผ่านพารามิเตอร์ไปยังงาน async ก็เป็นเช่นนี้

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

ประกาศและใช้งาน async เช่นที่นี่

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) การส่งผ่านวิธีการไปยัง async-task เพื่อหลีกเลี่ยงการเข้ารหัสโครงสร้างพื้นฐาน async-Task (thread, messagenhandler, ... ) หลาย ๆ ครั้งคุณอาจพิจารณาส่งผ่านวิธีการที่ควรดำเนินการใน async-task ของคุณเป็นพารามิเตอร์ ตัวอย่างต่อไปนี้สรุปแนวทางนี้ นอกจากนี้คุณอาจจำเป็นต้อง subclass async-task เพื่อส่งผ่านพารามิเตอร์การเตรียมใช้งานในตัวสร้าง

 /* 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

ทำไมอย่างไรและพารามิเตอร์ที่ส่งผ่านไปยัง Asynctask <> ดูรายละเอียดที่นี่ ฉันคิดว่ามันเป็นคำอธิบายที่ดีที่สุด

เอกสาร Android ของ Google กล่าวว่า:

งานอะซิงโครนัสถูกกำหนดโดยประเภททั่วไป 3 ประเภทเรียกว่า Params, Progress and Result และ 4 ขั้นตอนเรียกว่า onPreExecute, doInBackground, onProgressUpdate และ onPostExecute

ประเภททั่วไปของ AsyncTask:

สามประเภทที่ใช้โดยงานอะซิงโครนัสมีดังต่อไปนี้:

Params คือชนิดของพารามิเตอร์ที่ส่งไปยังงานเมื่อดำเนินการ ความคืบหน้าประเภทของหน่วยความคืบหน้าที่เผยแพร่ระหว่างการคำนวณพื้นหลัง ผลลัพธ์ประเภทของผลลัพธ์ของการคำนวณพื้นหลัง ไม่ใช่ทุกประเภทที่ใช้กับงานอะซิงโครนัสเสมอไป หากต้องการทำเครื่องหมายประเภทว่าไม่ได้ใช้เพียงแค่ใช้ประเภท Void:

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

คุณสามารถอ้างอิงเพิ่มเติมได้ที่: http://developer.android.com/reference/android/os/AsyncTask.html

หรือคุณสามารถล้างบทบาทของ AsyncTask ได้โดยอ้างถึงบล็อกของ Sankar-Ganesh

โครงสร้างของคลาส AsyncTask ทั่วไปมีลักษณะดังนี้:

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

    protected void onPreExecute(){ 

    } 

วิธีนี้จะดำเนินการก่อนเริ่มเธรดใหม่ ไม่มีค่าอินพุต / เอาต์พุตดังนั้นเพียงแค่เริ่มต้นตัวแปรหรืออะไรก็ตามที่คุณคิดว่าคุณต้องทำ

protected Z doInBackground(X...x){

}

วิธีการที่สำคัญที่สุดในคลาส AsyncTask คุณต้องวางทุกสิ่งที่คุณต้องการทำในพื้นหลังไว้ที่นี่ในเธรดที่แตกต่างจากหัวข้อหลัก ที่นี่เรามีอาร์เรย์ของวัตถุจากประเภท "X" เป็นค่าอินพุต (คุณเห็นในส่วนหัวหรือไม่เรามี "... ขยาย AsyncTask" นี่คือ TYPES ของพารามิเตอร์อินพุต) และส่งคืนวัตถุจากประเภท “Z”

โมฆะป้องกัน onProgressUpdate (Y y) {

} วิธีนี้เรียกว่าโดยใช้วิธีการ PublishProgress (y) และโดยปกติจะใช้เมื่อคุณต้องการแสดงความคืบหน้าหรือข้อมูลใด ๆ ในหน้าจอหลักเช่นแถบความคืบหน้าแสดงความคืบหน้าของการดำเนินการที่คุณกำลังทำอยู่เบื้องหลัง

โมฆะป้องกัน onPostExecute (Z z) {

} วิธีนี้เรียกว่าหลังจากการดำเนินการในพื้นหลังเสร็จสิ้น ในฐานะพารามิเตอร์อินพุตคุณจะได้รับพารามิเตอร์เอาต์พุตของเมธอด doInBackground

แล้วประเภท X, Y และ Z ล่ะ?

ดังที่คุณสามารถสรุปได้จากโครงสร้างข้างต้น:

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.

เราเรียกงานนี้จากชั้นเรียนนอกได้อย่างไร? ด้วยสองบรรทัดต่อไปนี้:

MyTask myTask = new MyTask();

myTask.execute(x);

โดยที่ x คือพารามิเตอร์อินพุตของประเภท X

เมื่อเราดำเนินงานแล้วเราสามารถค้นหาสถานะได้จาก“ ภายนอก” โดยใช้เมธอด“ getStatus ()”

myTask.getStatus (); และเราสามารถรับสถานะต่อไปนี้:

RUNNING - ระบุว่างานกำลังทำงานอยู่

กำลังรอ - แสดงว่างานยังไม่ได้ดำเนินการ

FINISHED - ระบุว่า onPostExecute (Z) เสร็จสิ้นแล้ว

คำแนะนำเกี่ยวกับการใช้ AsyncTask

อย่าเรียกใช้เมธอด onPreExecute, doInBackground และ onPostExecute ด้วยตนเอง ระบบจะทำโดยอัตโนมัติ

คุณไม่สามารถเรียก AsyncTask ภายใน AsyncTask หรือ Thread อื่นได้ การเรียกใช้เมธอดจะต้องดำเนินการในเธรด UI

เมธอด onPostExecute ถูกดำเนินการในเธรด UI (ที่นี่คุณสามารถเรียก AsyncTask อื่น!)

พารามิเตอร์อินพุตของงานอาจเป็นอาร์เรย์วัตถุด้วยวิธีนี้คุณสามารถใส่วัตถุและประเภทใดก็ได้ที่คุณต้องการ


4

คุณสามารถส่งผ่านพารามิเตอร์ในตัวสร้างงานหรือเมื่อคุณเรียกใช้ execute:

AsyncTask<Object, Void, MyTaskResult>

พารามิเตอร์แรก (Object) ถูกส่งผ่านใน doInBackground พารามิเตอร์ที่สาม (MyTaskResult) ถูกส่งกลับโดย doInBackground คุณสามารถเปลี่ยนเป็นประเภทที่คุณต้องการได้ จุดสามจุดหมายความว่าวัตถุเป็นศูนย์หรือมากกว่านั้น (หรืออาร์เรย์ของพวกมัน) อาจถูกส่งผ่านไปเป็นอาร์กิวเมนต์

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);

        }
    }

}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.