2013-07-15 52 views
0

當單擊複選框時,我的應用程序執行一個異步任務。我不能得到它不止一次記錄一條消息。它在第一次點擊上完成,但不會再次完成。在環顧其他問題後,我確定我必須建立一個自定義類,當然還要調用新的MyAysncTask(我已經在做),但它仍然無法正常工作。創建新對象時Android異步任務不執行

這是在單擊複選框時執行的代碼。

cbJoining.setOnClickListener(new OnClickListener() 
{ 
    public void onClick(View v) 
    { 
     new MyAsyncTask(EventID, cbJoining.isChecked(), URL_Race, sDates, sState).execute(); 
    } 
}); 

這裏是自定義類

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

    public String EventID; 
    public boolean bJoin; 
    public String URL_Race; 
    public String sDates; 
    public String sState; 

    public MyAsyncTask(String myEventID, boolean mybJoin, String myURL_Race, String mysDates, String mysState){ 
     super(); 
     EventID = myEventID; 
     bJoin = mybJoin; 
     URL_Race = myURL_Race; 
     sDates = mysDates; 
     sState = mysState; 
    } 

    protected void onPreExecute() { 
    }; 

    @Override 
    protected Void doInBackground(Void... args) { 

     //Looper.prepare(); 

     API oAPI = new API(); 
     oAPI.Join(mPrefs, EventID, bJoin, URL_Race, sDates, sState); 

     Log.d("ASYNCTASK", URL_Race); 

     //Looper.loop(); 

     return null; 
    } 

    protected void onPostExecute(Void result) { 
     Log.d("ASYNCTASK", "Finished"); 
    }; 
} 

這裏是異常: 十二月7日至16日:45:10.286:E/AndroidRuntime(28309):致命異常:的AsyncTask#2

07-16 12:45:10.286 E/AndroidRuntime(28309):java.lang.RuntimeException:執行doInBackground()時發生錯誤

07-16 12:45:10.286:E/AndroidRuntime(28309) :在andro id.os.AsyncTask $ 3.done(AsyncTask.java:299)

07-16 12:45:10.286:E/AndroidRuntime(28309):在java.util.concurrent.FutureTask.finishCompletion(FutureTask.java: 352)

07-16 12:45:10.286:E/AndroidRuntime(28309):在java.util.concurrent.FutureTask.setException(FutureTask.java:219)

07-16 12:45: 10.286:E/AndroidRuntime(28309):在java.util.concurrent.FutureTask.run(FutureTask.java:239)

07-16 12:45:10.286:E/AndroidRuntime(28309):at android.os .AsyncTask $ SerialExecutor $ 1.run(AsyncTask.java:230)

12月7日至16日:45:10.286:E/AndroidRuntime(28309):在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)

12月7日至16日:45:10.286: E/AndroidRuntime(28309):在java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:573)

07-16 12:45:10.286:E/AndroidRuntime(28309):at java.lang .Thread.run(Thread.java:856)

07-16 12:45:10.286:E/AndroidRuntime(28309):引起:java.lang.RuntimeException:無法在線程內創建處理程序稱爲Looper.prepare()

12月7日至16日:45:10.286:E/AndroidRuntime(28309):在android.os.Handler(Handler.java:197)

12月7日至16日:45:10.286:E/AndroidRuntime( 28309):at android.os.Handler。(Handler.java:111)

07-16 12:45:10.286:E/AndroidRuntime(28309):at android.app.Activity。(Activity.java:759 )

07-16 12:45:10.286:E/AndroidRuntime(28309):在com.chartermatrixllc.motocrossmatrix.API $ FB(API.java:88)

07-16 12:45: 10.286:E/AndroidRuntime(28309):在com.charter matrixllc.motocrossmatrix.API.Join(API.java:125)

07-16 12:45:10.286:E/AndroidRuntime(28309):at com.chartermatrixllc.motocrossmatrix.Race $ MyAsyncTask.doInBackground(Race。的java:207)

07-16 12:45:10.286:E/AndroidRuntime(28309):在com.chartermatrixllc.motocrossmatrix.Race $ MyAsyncTask.doInBackground(Race.java:1)

07-16 12:45:10.286:E/AndroidRuntime(28309):at android.os.AsyncTask $ 2.call(AsyncTask.java:287)

07-16 12:45:10.286:E/AndroidRuntime(28309):at java.util.concurrent.FutureTask.run(FutureTask.java:234)

12月7日至16日:45:10.286:E/AndroidRuntime(28309):... 4更

+0

我不知道,如果這是你的問題,但是從這個代碼,我看不出有任何需要爲'Looper.prepare()'和'Looper.loop()'。如果你確實需要它,那麼你應該調用'Looper.quit()' – codeMagic

+0

什麼是API類? – Desert

回答

2

你可能工作在Android 4+,從該版本AsyncTask只有一個線程,你

Looper.prepare(); 

    Log.d("ASYNCTASK", "Clicked"); 

    Looper.loop(); 

所以,現在你有幾個選項阻止它:

1)使用方法AsyncTask.executeOnExecutor,並提供你自己執行器與一些數量的線程,例如Executors.newCachedThreadPool()

2)停止阻止AsyncTask螺紋

+0

假設我想做更多而不是日誌,比如說下載一些JSON,我該如何停止阻塞線程?當我刪除Looper.prepare和Looper.loop()時,在執行像下載數據這樣的長時間任務時出現異常,告訴我必須包含looper.prepare() – masteroleary

+0

如果您只想執行長時間運行的任務,需要調用 'Looper.prepare(); Looper.loop();'。只需編寫這個任務的代碼即可。 – Desert

+0

我認爲,但沒有它,我得到這個異常時,首先調用它:\t 不能內螺紋已不叫Looper.prepare()我只是想將一些數據發送到服務器不止一次 – masteroleary

0

Looper不應被附接到工人螺紋在AsyncTask出於多種原因,其中主要的兩個是:

  1. 如果Looper.loop()被調用時,工作線程忙於處理和等待傳入的消息,即它會阻止線程,這樣,沒有其他任務可以執行。這總是一件壞事,但它是API級別11之後的應用性能殺手,其中AsyncTask.execute()按順序處理任務,使得連續任務等待阻塞任務完成。
  2. 即使只調用Looper.prepare(),工作線程也會與消息隊列關聯。這隻能執行一次,因此第二次執行任務並再次調用Looper.prepare()時,會引發RuntimeException。因此,AsyncTask只能執行一次。

從代碼示例目前尚不清楚爲什麼你的工作線程需要Looper,但如果它是一個要求,你不應該使用AsyncTask而是一個HandlerThreadHandlerThread是帶有Looper的後臺線程。缺點是你必須自己處理在UI線程和後臺線程之間傳遞的消息。

+0

我加Looper.loop(),因爲當我跑的應用,但不它有一個異常說明**不能創建處理程序內部線程沒有調用Looper.prepare()** 我只是試圖發送一些數據到服務器不止一次。 – masteroleary

+0

「Handler」創建在哪裏?在你的代碼或平臺/庫代碼中? – AndersGoransson

+0

我很抱歉,該處理程序行不應該在那裏。我最初是從另一個可用的應用程序中的代碼開始的,但我認爲新API的更改已經打破了它。我花了很多時間去嘗試我在網上找到的多種解決方案,但沒有成功,Handler系列從其中一個測試中遺留下來。現在我正在按照您的建議查看HandlerThread。我顯然無能爲力,可能會因各種API級別的衆多示例而感到困惑。 – masteroleary

0

試試這個,

runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
     new MyAsyncTask(EventID, cbJoining.isChecked(), URL_Race, sDates, sState).execute(); 
      } 
     }); 

任何其他的AsyncTask相關疑問ü可以參考, https://stackoverflow.com/a/36078608/2249287