Android SDK AsyncTask doInBackground ไม่ทำงาน (คลาสย่อย)


90

ณ วันที่ 15/2/2012 ฉันยังไม่พบคำอธิบายที่ดีหรือเหตุผลว่าทำไมจึงใช้ไม่ได้ วิธีแก้ปัญหาที่ใกล้เคียงที่สุดคือการใช้วิธีเธรดแบบเดิมแต่เหตุใดจึงรวมคลาสที่ไม่ (ดูเหมือนจะ) ทำงานใน Android SDK

Evenin 'SO!

ฉันมีคลาสย่อย AsyncTask:

// ParseListener had a callback which was called when an item was parsed in a
// RSS-xml, but as stated further down it is not used at all right now.
private class xmlAsync extends AsyncTask<String, RSSItem, Void> implements ParseListener

ที่ดำเนินการดังนี้:

xmlAsync xmlThread = new xmlAsync();

xmlThread.execute("http://www.nothing.com");

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

@Override
protected Void doInBackground(String... params) 
{
    Log.v(TAG, "doInBackground");
        return null;
}

ซึ่งด้วยเหตุผลบางอย่างไม่ได้บันทึกอะไรเลย อย่างไรก็ตามฉันได้เพิ่มสิ่งนี้:

@Override
protected void onPreExecute() 
{
        Log.v(TAG, "onPreExecute");
        super.onPreExecute();
}

และบรรทัดนั้นจะถูกบันทึกเมื่อเรียกใช้เธรด ดังนั้นอย่างใด onPreExecute () เรียกว่า แต่ไม่ doInBackground () ฉันมี AsyncTask อื่นที่ทำงานในพื้นหลังในเวลาเดียวกันซึ่งใช้งานได้ดี

ฉันกำลังใช้งานแอปบนโปรแกรมจำลอง SDK เวอร์ชัน 15, Eclipse, Mac OS X 10.7.2 ใกล้กับขั้วโลกเหนือ

แก้ไข:

@Override
    protected void onProgressUpdate(RSSItem... values) {

        if(values[0] == null)
        {
                            // activity function which merely creates a dialog
            showInputError();
        }
        else
        {

            Log.v(TAG, "adding "+values[0].toString());
            _tableManager.addRSSItem(values[0]);
        }


        super.onProgressUpdate(values);
    }

_tableManager.addRSSItem () มากหรือน้อยจะเพิ่มแถวไปยัง SQLiteDatabase โดยเริ่มต้นด้วยบริบทของกิจกรรม PublishProgress () ถูกเรียกโดยการเรียกกลับของ Interface ParseListener อย่างไรก็ตามเนื่องจากฉันไม่ได้ทำอะไรเลยนอกจาก log.v ใน doInBackground () ฉันจึงพบว่าสิ่งนี้ไม่จำเป็นที่จะต้องเปิดขึ้นมา

แก้ไข 2:

เอาล่ะเพื่อให้ชัดเจนอย่างสมบูรณ์นี่คือ AsyncTask อื่นที่ทำงานในกิจกรรมเดียวกันและทำงานได้ดีอย่างสมบูรณ์

private class dbAsync extends AsyncTask<Void, RSSItem, Void>
{
    Integer prevCount;
    boolean run;

    @Override
    protected void onPreExecute() {
        run = true;
        super.onPreExecute();
    }

    @Override
    protected Void doInBackground(Void... params) {
        // TODO Auto-generated method stub
        run = true;
        prevCount = 0;

        while(run)
        {
            ArrayList<RSSItem> items = _tableManager.getAllItems();

            if(items != null)
            {
                if(items.size() > prevCount)
                {
                    Log.v("db Thread", "Found new item(s)!");
                    prevCount = items.size();

                    RSSItem[] itemsArray = new RSSItem[items.size()];

                    publishProgress(items.toArray(itemsArray));
                }
            }               

            SystemClock.sleep(5000);
        }

        return null;
    }

    @Override
    protected void onProgressUpdate(RSSItem... values) {

        ArrayList<RSSItem> list = new ArrayList<RSSItem>();

        for(int i = 0; i < values.length; i++)
        {
            list.add(i, values[i]);
        }

        setItemsAndUpdateList(list);

        super.onProgressUpdate(values);
    }

    @Override
    protected void onCancelled() {
        run = false;

        super.onCancelled();
    }
}

แก้ไข 3:

เฮ้อขอโทษที่ถามคำถามไม่ดี แต่นี่คือการเริ่มต้นของงาน

xmlAsync _xmlParseThread;
dbAsync _dbLookup;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

_dbLookup = new dbAsync();
_dbLookup.execute();

_xmlParseThread = new xmlAsync();       
_xmlParseThread.execute("http://www.nothing.com", null);
}

เป็นไปได้หรือไม่ที่กิจกรรมจะเสร็จสิ้นก่อนงานจะเสร็จสิ้น
Paul Nikonowicz

ไม่น่าเป็นไปได้สูง ในกรณีนี้เธรดอื่นของฉันจะไม่ทำงานใช่ไหม ตอนนี้ฉันมีกิจกรรมเพียงอย่างเดียว
SeruK

2
แอปของฉันมีปัญหาเดียวกัน - doInBackground ไม่ได้ถูกเรียกหรือถูกเรียกด้วยความล่าช้าที่ยาวนานมาก นี่คือข้อสังเกตที่ จำกัด ของฉัน: รหัสเดียวกันทำงานได้อย่างไม่มีที่ติบนสมาร์ทโฟน Android 2.3.3 และตัวจำลอง Android 2.3.3 แต่มีปัญหานี้ในแท็บเล็ต Android 4.0.3 และตัวเลียนแบบ Android 4.xx จำนวนมาก เป็นเรื่องที่น่าดึงดูดมากที่จะสรุปว่าปัญหานี้เกิดขึ้นใน Android เวอร์ชันใหม่กว่า
Hong

ขออภัยฉันลืมที่จะพูดถึงปัญหานี้เกิดขึ้นเฉพาะกับ AsyncTask ที่สองของกิจกรรม AsyncTask แรกทำงานได้ดีเสมอ
Hong

ฮงลองคำตอบของ Matthieu แล้วหรือยัง? ส่วนใหญ่ฉันไม่ได้ใช้ ATM ของเกม Android และไม่ได้ใช้งานมาระยะหนึ่งแล้วดังนั้นฉันจึงไม่สามารถบอกได้ว่าคำตอบของเขาใช้งานได้จริงหรือไม่ ถ้ามันไม่เหมาะกับคุณฉันคงแย่ที่ต้องยอมรับคำตอบของเขา ...
SeruK

คำตอบ:


108

วิธีแก้ปัญหาของ Matthieu จะใช้ได้ดีสำหรับคนส่วนใหญ่ แต่บางคนอาจประสบปัญหา เว้นแต่จะขุดในลิงค์ต่างๆที่มีให้ที่นี่หรือจากเว็บเช่นคำอธิบายของAnders Göransson ฉันกำลังพยายามสรุปการอ่านอื่น ๆ ที่นี่และอธิบายวิธีแก้ปัญหาอย่างรวดเร็วหาก executeOnExecutor ยังคงทำงานในเธรดเดียว ...

พฤติกรรมของการAsyncTask().execute();เปลี่ยนแปลงในเวอร์ชัน Android ก่อนที่งานของDonut (Android: 1.6 API: 4)จะถูกดำเนินการตามลำดับตั้งแต่DonutไปจนถึงGingerbread (Android: 2.3 API: 9)งานที่ดำเนินการขนานกัน เนื่องจากการดำเนินการของHoneycomb (Android: 3.0 API: 11)ถูกเปลี่ยนกลับไปเป็นลำดับ AsyncTask().executeOnExecutor(Executor)อย่างไรก็ตามมีการเพิ่มวิธีการใหม่สำหรับการดำเนินการแบบขนาน

ในการประมวลผลตามลำดับงาน Async ทั้งหมดจะรันในเธรดเดียวดังนั้นจึงต้องรอก่อนที่งานก่อนหน้านี้จะจบลง หากคุณต้องการรันโค้ดทันทีคุณต้องมีการประมวลผลงานแบบขนานในเธรดที่แยกจากกัน

ด้วยการดำเนินการแบบอนุกรม AsyncTask จะไม่สามารถใช้ได้ระหว่างเวอร์ชัน Donut และ Honeycomb ในขณะที่การดำเนินการแบบขนานไม่สามารถใช้งานได้ก่อน Donut

สำหรับการประมวลผลแบบขนานหลังจาก Donut: ตรวจสอบเวอร์ชัน Build และขึ้นอยู่กับวิธีการใช้. execute () หรือ. executeOnExecutor () รหัสต่อไปนี้ช่วยได้ ...

AsyncTask<Void,Void,Void> myTask = new AsyncTask<Void,Void,Void>() { ... }; // ... your AsyncTask code goes here
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB)
    myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else
    myTask.execute();

NOTE:ฟังก์ชั่น.executeOnExecutor()ตรวจสอบว่าtargetSdkVersionโปรเจ็กต์น้อยกว่าหรือเท่ากับHONEYCOMB_MR1(Android: 2.1 API: 7) จากนั้นจะบังคับให้ตัวดำเนินการเป็นTHREAD_POOL_EXECUTOR(ซึ่งรัน Tasks ตามลำดับในโพสต์ Honeycomb)
หากคุณไม่ได้กำหนดไว้targetSdkVersionแล้วคือการพิจารณาโดยอัตโนมัติจะเป็นminSdkVersion ดังนั้นสำหรับการเรียกใช้ AsyncTask ของคุณแบบขนานบนโพสต์ Honeycomb คุณไม่สามารถปล่อยว่างไว้ได้targetSdkVersion
targetSdkVersion


1
ตอบได้ดีมาก. แม้ว่า Matthieu จะไม่ผิด แต่ฉันก็ยอมรับสิ่งนี้เนื่องจากคุณเพิ่มข้อมูลสำคัญจำนวนมาก
SeruK

@Nashe ขอบคุณมาก. เป็นประโยชน์มากจริงๆ ฉันต่อสู้กับปัญหาเดียวกันนี้เป็นเวลา 3 วัน ขอบคุณอีกครั้ง :)

บันทึกวันของฉัน! หวังว่าคำตอบนี้จะหาได้ง่ายขึ้น
zjk

4
เฮ้ @ นาเช่ปัญหาของฉันมันน่าอึดอัดเล็กน้อย ก่อนหน้านี้ฉันใช้เมธอด. execute () บน AsyncTask และโค้ดก็ทำงานได้อย่างสมบูรณ์แบบ แต่วันนี้ฉันพบปัญหา - ตัวควบคุมไม่เข้าสู่เมธอด doInBackground () แม้ว่าโซลูชันที่คุณให้จะใช้งานได้ แต่ฉันก็งงงวยว่าก่อนหน้านี้ใช้งานได้อย่างไรโดยไม่มีวิธีแก้ปัญหา ฉันใช้อุปกรณ์ชุดเดียวกันก่อนและตอนนี้
Ravi Sisodia

ทำไมถึงเป็นแบบนี้? ทำไมมันไม่ได้ผลตามความคาดหวัง? :(
Nikolay R

160

คุณควรชำระเงินคำตอบนี้: https://stackoverflow.com/a/10406894/347565และลิงก์ไปยังกลุ่ม Google ที่มีอยู่

ฉันมีปัญหาคล้ายกับคุณ แต่ยังไม่ชัดเจนว่าทำไมมันถึงใช้งานไม่ได้ แต่ฉันเปลี่ยนรหัสเป็นแบบนี้และปัญหาก็หายไป:

ASyncTask<Void,Void,Void> my_task = new ASyncTask<Void,Void,Void>() { ... };
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
    my_task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null);
else
    my_task.execute((Void[])null);

ฉันแย่มากที่มองย้อนกลับไปที่โพสต์นี้ ฉันย้ายออกจากโครงการไปนานแล้ว ฉันจะยอมรับสิ่งนี้เป็นคำตอบเนื่องจากดูเหมือนว่าผู้คนจะบอกว่ามันได้ผล
SeruK

ตอนนี้ใช้ได้ผลสำหรับฉัน แต่ฉันหวังว่าฉันจะเข้าใจว่าทำไม มันทำงานได้ดีกับ execute ก่อนที่มันจะหยุด สิ่งหนึ่งที่ฉันกำลังทำคือเริ่ม asynctask ใหม่ภายใน onPostExecute ของ asynctask เดียวกัน (เช่นฉันเรียกมันซ้ำ) อาจจะเชื่อมต่อกับปัญหาหรือไม่
สตีฟ

ฉันคิดว่าสิ่งนี้ควรให้คำอธิบายทั้งหมดที่คุณต้องการ: commonsware.com/blog/2012/04/20/…
Matthieu

1
@ Matthieu: ครับผมขอบคุณมากไม่พอ !!! ฉันตีหัวกับปัญหานี้มาหลายชั่วโมงแล้วและวิธีแก้ปัญหาของคุณทำให้ทุกอย่างเป็นไปอย่างมีเสน่ห์ ขอบคุณมากสำหรับคำตอบที่ยอดเยี่ยม ฉันหวังว่าฉันจะโหวตมากกว่าหนึ่งโหวต !!
Swayam


9

คุณสามารถทำได้สองวิธี:

วิธีที่ 1 :

if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) // Above Api Level 13
  {
      asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
  }
else // Below Api Level 13
  {
      asyncTask.execute();
  }

ในกรณีที่มีวิธีที่ 1ไม่ทำงานสำหรับคุณลองวิธีที่ 2

วิธีที่ 2 :

int mCorePoolSize = 60;
int mMaximumPoolSize = 80;
int mKeepAliveTime = 10;
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(mMaximumPoolSize);
Executor mCustomThreadPoolExecutor = new ThreadPoolExecutor(mCorePoolSize, mMaximumPoolSize, mKeepAliveTime, TimeUnit.SECONDS, workQueue);
asyncTask.executeOnExecutor(mCustomThreadPoolExecutor);

หวังว่านี่จะช่วยคุณได้


มันใช้งานได้ดี แต่งาน Async ถัดไปที่ใช้ AsyncTask กำลังทำงานล้มเหลวดังนั้นฉันต้องเปลี่ยนด้วย CustomExecutor ในทุกโครงการฉันเดา :(
kumar

@vinu ฉันขอแนะนำให้คุณใช้งาน async ทั่วไปและวิธีการทั่วไปในการดำเนินการ AsyncTask หวังว่านี่จะช่วยคุณได้
Hiren Patel

2
นี่ช่วยฉันได้มาก! ขอบคุณ!
Justin Ebby

6

ฉันมีปัญหาเดียวกัน: ไม่สามารถเรียกใช้ AsyncTask ที่สองหลังจากที่ฉันเรียกว่า "execute" ในอันแรกได้: doInBackground ถูกเรียกสำหรับอันแรกเท่านั้น

หากต้องการตอบว่าเหตุใดจึงเกิดขึ้นให้ตรวจสอบคำตอบนี้(พฤติกรรมที่แตกต่างกันขึ้นอยู่กับ SDK)

อย่างไรก็ตามสำหรับกรณีของคุณอุปสรรคนี้สามารถหลีกเลี่ยงได้โดยใช้ executeOnExecutor (ใช้ได้ตั้งแต่ 3.0 สำหรับฉันโดยใช้ 4.0.3) แต่ระวังข้อ จำกัด ของขนาดเธรดพูลและการจัดคิว

ลองทำแบบนี้ได้ไหม:

xmlAsync _xmlParseThread;
dbAsync _dbLookup;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

_dbLookup = new dbAsync();
_dbLookup.execute();

_xmlParseThread = new xmlAsync();       
_xmlParseThread.executeOnExecutor(_dbLookup.THREAD_POOL_EXECUTOR
 ,"http://www.nothing.com", null);
}

สำหรับคำถามการอัปเดตของคุณ: มีการอธิบายไว้ในเอกสาร โดยทั่วไปเพื่อหลีกเลี่ยงปัญหาทั้งหมดที่อาจมาจากการอ่านหลายเธรดเช่นการแทรกแซง ...


5

สิ่งหนึ่งที่ฉันอยากรู้และมันอาจช่วยแก้ปัญหาของคุณได้จริง ๆ คุณกำลังสร้างอินสแตนซ์ของชั้นเรียนของคุณและเรียกใช้เมธอด execute () อยู่ที่ไหน หากคุณอ่านเอกสารสำหรับ AsyncTask การดำเนินการทั้งสองจะต้องเกิดขึ้นบนเธรด UI หลัก หากคุณกำลังสร้างออบเจ็กต์ของคุณและเรียกใช้ execute จากเธรดอื่น onPreExecute อาจเริ่มทำงานฉันไม่แน่ใจ 100% ที่นี่ แต่เธรดพื้นหลังจะไม่ถูกสร้างและดำเนินการ

หากคุณกำลังสร้างอินสแตนซ์ของ AsyncTask ของคุณจากเธรดพื้นหลังหรือการดำเนินการอื่น ๆ ที่ไม่เกิดขึ้นบนเธรด UI หลักคุณสามารถพิจารณาใช้วิธีการ: Activity.runOnUiThread (Runnable)

คุณจะต้องเข้าถึงอินสแตนซ์ของกิจกรรมที่กำลังทำงานของคุณเพื่อเรียกใช้เมธอดนั้น แต่จะช่วยให้คุณสามารถรันโค้ดบนเธรด UI จากโค้ดอื่น ๆ ที่ไม่ได้ทำงานบนเธรด UI

หวังว่าจะสมเหตุสมผล โปรดแจ้งให้เราทราบหากสามารถช่วยเหลือเพิ่มเติมได้

เดวิด


เพิ่มคำตอบของคุณกระทู้นี้มีคำตอบที่น่าสนใจstackoverflow.com/questions/4080808/… .
manjusg

ขอบคุณสำหรับคำตอบที่ดี! ฉันเพิ่มสิ่งนี้เพราะฉันคิดว่านั่นอาจเป็นปัญหาทั่วไปของ AsyncTask-beginner อนิจจามันไม่ใช่คำตอบที่ถูกต้องสำหรับปัญหานี้ คลาสทั้งสองถูกสร้างอินสแตนซ์ใน onCreate () ของกิจกรรมที่รันบนเธรด UI หลัก ฉันมีกิจกรรมเดียวในโครงการนี้
SeruK

@manjusg ฉันได้พิจารณามาโดยตลอดว่ามันมีส่วนเกี่ยวข้องกับการที่ AsyncTask ไม่เสถียรบางทีอาจจะเพิ่มมากขึ้นเมื่อทำงานหลายอย่างพร้อมกัน ถ้าเป็นเช่นนั้นทำไม?
SeruK

ฉันไม่รู้จริงๆว่า SO มีนโยบายอะไรเกี่ยวกับการโพสต์อย่างรวดเร็วสามครั้งติดต่อกัน แต่ฉันพบสิ่งนี้ในอีกหัวข้อ ... foo.jasonhudgins.com/2010/05/limitations-of-asynctask.html "AsyncTask ใช้ คิวงานภายในแบบคงที่โดย จำกัด ฮาร์ดโค้ดไว้ที่ 10 องค์ประกอบ " นี่อาจพิสูจน์อะไรบางอย่างได้ แต่ฉันมี AsyncTask-subclasses สองอินสแตนซ์ ฉันต้องการหลีกเลี่ยงการใช้วิธีการเธรดปกติเนื่องจากในที่สุดจะมีการแยกวิเคราะห์จำนวนมากใน dere
SeruK

2

Android โหด! ฉันไม่อยากจะเชื่อเลยว่าการใช้งานที่ไม่ดีที่เปลี่ยนแปลงไปจากวันนี้เป็นวันนี้ วันหนึ่งมันเป็นเธรดเดียวอีก 5 เธรดถัดไปคือ 128

อย่างไรก็ตามนี่คือการแทนที่หุ้น AsyncTask เกือบจะลดลง คุณสามารถเรียกมันว่า AsyncTask ได้หากต้องการ แต่เพื่อหลีกเลี่ยงความสับสนเรียกว่า ThreadedAsyncTask คุณต้องเรียกใช้ executeStart () แทน execute เนื่องจาก execute () ถือเป็นที่สิ้นสุด

/**
 * @author Kevin Kowalewski
 *
 */
public abstract class ThreadedAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> { 
    public AsyncTask<Params, Progress, Result> executeStart(Params... params){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
            return executePostHoneycomb(params);
        }else{
            return super.execute(params);
        }
    }


    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    private AsyncTask<Params, Progress, Result> executePostHoneycomb(Params... params){
        return super.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params); 
    }
}

เดี๋ยวก่อนคุณไม่ได้บอกว่า Android บางเวอร์ชัน จำกัด async ops ไว้ที่เธรดเดียวใช่ไหม นั่นจะโง่อย่างไม่น่าเชื่อ (ฉันออกจากเกม Android มาระยะหนึ่งแล้ว :))
SeruK

ใช่บน Android 3.0+ หากคุณไม่ได้ใช้ AsyncTask.THREAD_POOL_EXECUTOR คุณจะได้เธรดพูลเพียงชุดเดียว ลองด้วยตัวคุณเอง AsyncTask สองตัวแล้วนอนใน doInBackground จากเอกสาร AsyncTask ของ Android: "เริ่มต้นด้วย HONEYCOMB งานจะดำเนินการบนเธรดเดียวเพื่อหลีกเลี่ยงข้อผิดพลาดทั่วไปของแอปพลิเคชันที่เกิดจากการทำงานแบบขนาน"
Kevin Parker

1

ฉันรู้ว่านี่อาจจะสายไปแล้วสำหรับเธรด แต่มีเหตุผลว่าทำไมมันจึงใช้ไม่ได้กับตัวเลียนแบบ Android ในภายหลัง เมื่อ asynctask เปิดตัว android ให้คุณรันทีละตัวเท่านั้นจากนั้นบางครั้งหลังจากนั้นฉันไม่แน่ใจว่าเวอร์ชันใดพวกเขาอนุญาตให้คุณเรียกใช้ asynctasks หลายรายการพร้อมกันซึ่งทำให้เกิดปัญหาในแอพจำนวนมากดังนั้นใน Honeycomb + จะเปลี่ยนกลับเป็นเพียง อนุญาตให้ asynctask หนึ่งตัวทำงานพร้อมกัน เว้นแต่คุณจะเปลี่ยนเธรดพูลด้วยตนเอง หวังว่าจะกระจ่างขึ้นหนึ่งหรือสองอย่างสำหรับผู้คน


0

ฉันคิดว่ามันเป็น sdk ฉันมีปัญหาเดียวกันและหลังจากเปลี่ยน sdk เป้าหมายจาก 15 เป็น 11 ทุกอย่างทำงานได้อย่างสมบูรณ์

ด้วย sdk15 แม้ว่าสถานะ AsyncTask.Status กำลังทำงานอยู่ แต่ doInBackground จะไม่ถูกเรียก ฉันคิดว่ามันมีส่วนเกี่ยวข้องกับเธรด ui


ฉันไม่สามารถปฏิเสธหรือยืนยันได้เนื่องจากตอนนี้ฉันไม่มีเวลาทดสอบจริงๆ ทั้งหมดที่ฉันสามารถพูดได้คือฉันใช้ SDK 15 ดังนั้นจึงมีโอกาสมาก
SeruK

0

ตามคำตอบของ Matthieu ด้านล่างผู้ช่วยคลาสตัวเพื่อดำเนินการของคุณAsyncTaskอย่างถูกต้องโดยขึ้นอยู่กับเวอร์ชัน SDK เพื่อหลีกเลี่ยงการทำรหัสซ้ำในแอปพลิเคชันของคุณ:

import android.annotation.SuppressLint;
import android.os.AsyncTask;
import android.os.Build;

public class AsyncTaskExecutor<Params, Progress, Result> {

  @SuppressLint("NewApi")
  public AsyncTask<Params, Progress, Result> execute(final AsyncTask<Params, Progress, Result> asyncTask, final Params... params){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
      return asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
    }  else{
      return asyncTask.execute(params);
    }
  }

}

ตัวอย่างการใช้งาน:

public class MyTask extends AsyncTask<Void, Void, List<String>> {

...

final MyTask myTask = new MyTask();
new AsyncTaskExecutor<Void, Void, List<String>>().execute(myTask);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.