2012-05-17 52 views
0

我正在計算需要一些時間的事情。爲此,我已經創建了一個子類的AsyncTask一個內部類:AsyncTask錯誤困惑

private class AsyncAllPlayAll extends AsyncTask<String, Void, CharSequence> 
{ 
    StournamentDbAdapter mDbHelper; 

    public AsyncAllPlayAll(Context context, StournamentDbAdapter dbHelper) 
    { 
     this.mContext = context; 
     this.mDbHelper = dbHelper; 
    } 

    @Override 
    protected CharSequence doInBackground(String... tournamentRowIds) 
    { 
     Long tournamentRowId = Long.valueOf(tournamentRowIds[0]); 

     Tournament tournament = new Tournament(mDbHelper, tournamentRowId); 
     tournament.setupTournament();    

     Boolean tournamentHasWinner = mDbHelper.winningTournamentParticipantsExists(tournamentRowId); 

     // tournament already run: delete score 
     if(tournamentHasWinner) 
     { 
      mDbHelper.resetTournamentsStocksScore(tournamentRowId); 

      mDbHelper.resetTournamentWinnerStockId(tournamentRowId); 
     } 

     //run tournament! 
     tournament.allPlayAll();     

     TournamentParticipant tournamentParticipant = mDbHelper.insertWinningParticipant(tournamentRowId);      

     populateCompetitorsListView();  

     final CharSequence winner = "Winner is: " + tournamentParticipant.getStock().getName() + "(" + tournamentParticipant.getScore() + ")"; 

     return winner; 
    } 

    @Override        //the winner 
    protected void onPostExecute(final CharSequence result) { 

     super.onPostExecute(result);  

     final int duration = Toast.LENGTH_LONG; 

     TournamentEdit.this.runOnUiThread(new Runnable() { 
      public void run() { 
       Toast.makeText(mContext, "Hello", duration).show(); 
      } 
     }); 

    } 

} 

但我得到一個錯誤,我不放棄明白了:「不能內螺紋已不叫Looper.prepare創建處理程序()

我在stackoverflow上讀了幾個線程,但是實現了它們寫入的內容並沒有改變我的情況。

我確定錯誤來自於我在onPostExecute中運行的Toast,但這不是問題。該錯誤發起嘗試初始化錦標賽。

Tournament tournament = new Tournament(mDbHelper, tournamentRowId); 

這裏是我的籌碼:

Thread [<11> AsyncTask #1] (Suspended) 
    FragmentManagerImpl$1.<init>(FragmentManagerImpl) line: 423 
    FragmentManagerImpl.<init>() line: 423 
    Tournament(Activity).<init>() line: 702 
    Tournament.<init>(StournamentDbAdapter, Long) line: 48 
    TournamentEdit$AsyncAllPlayAll.doInBackground(String...) line: 346 
    TournamentEdit$AsyncAllPlayAll.doInBackground(Object...) line: 1  
    AsyncTask$2.call() line: 264  
    FutureTask$Sync.innerRun() line: 305  
    AsyncTask$3(FutureTask).run() line: 137 
    AsyncTask$SerialExecutor$1.run() line: 208 
    ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1076 
    ThreadPoolExecutor$Worker.run() line: 569 
    Thread.run() line: 856 

我tohught它可能是一些問題與分貝線程?當我從主線程傳遞給AsyncAllPlayAll時。

於是,我就打開內部類的分貝線程(不同的實例),並改變了它的構造函數:

public AsyncAllPlayAll(Context context, StournamentDbAdapter dbHelper) 
    { 
     this.mContext = context; 
     this.mDbHelper = dbHelper; 
     mDbHelper = new StournamentDbAdapter(context); 
     mDbHelper.open(); 
    } 

這並沒有幫助:(

現在我嘗試添加一個尺蠖(如AsyncTask and Looper.prepare() error建議)

@Override 
    protected CharSequence doInBackground(String... tournamentRowIds) 
    { 
     Looper.prepare(); 
     Long tournamentRowId = Long.valueOf(tournamentRowIds[0]); 

     Tournament tournament = new Tournament(mDbHelper, tournamentRowId); 
     tournament.setupTournament();    

     Boolean tournamentHasWinner = mDbHelper.winningTournamentParticipantsExists(tournamentRowId); 

     // tournament already run: delete score 
     if(tournamentHasWinner) 
     { 
      mDbHelper.resetTournamentsStocksScore(tournamentRowId); 

      mDbHelper.resetTournamentWinnerStockId(tournamentRowId); 
     } 

     //run tournament! 
     tournament.allPlayAll();     

     TournamentParticipant tournamentParticipant = mDbHelper.insertWinningParticipant(tournamentRowId);      

     populateCompetitorsListView();  

     final CharSequence winner = "Winner is: " + tournamentParticipant.getStock().getName() + "(" + tournamentParticipant.getScore() + ")"; 

     Looper.loop(); 

     return winner; 
    } 

代碼走得更遠,但我得到了以下錯誤:

引起:android.view.ViewRootImpl $ CalledFromWrongThreadException:只有創建視圖層次結構的原始線程可以觸及其視圖。

現在populateCompetitorsListView()是導致飛機失事的原因,它也清楚爲什麼:看populateCompetitorsListView()的最後一行,這是

setListAdapter(tournamentStocks); 

試圖改變主線程。我將它移到了主類中,這似乎修正了它:計算運行。

@SuppressWarnings("deprecation") 
private void populateCompetitorsListView() 
{ 
    // Get all of the notes from the database and create the item list 
    Cursor tournamentStocksCursor = mDbHelper.retrieveTrounamentStocks(mTournamentRowId); 
    startManagingCursor(tournamentStocksCursor); 

    // Create an array to specify the fields we want to display in the list (only name) 
    String[] from = new String[] {StournamentConstants.TblStocks.COLUMN_NAME, StournamentConstants.TblTournamentsStocks.TBL_COLUMN_TOURNAMENTS_STOCKS_STOCK_SCORE}; 

    // and an array of the fields we want to bind those fields to (in this case just name) 
    int[] to = new int[]{R.id.competitor_name, R.id.competitor_score}; 

    // Now create an array adapter and set it to display using our row 
    SimpleCursorAdapter tournamentStocks = new SimpleCursorAdapter(this, R.layout.competitor_row, tournamentStocksCursor, from, to); 

    //tournamentStocks.convertToString(tournamentStocksCursor); 
    setListAdapter(tournamentStocks);  
} 

但現在的問題是,我似乎被卡住內doInBackground()由於Looper.loop()的執行情況;這是猜測運行無止境的循環?

有沒有進一步的想法?

謝謝!

回答

0

經過大量的研究,我發現我的問題是什麼:我在doInBackground()&裏面使用了太多的代碼,然後把大部分代碼拿回來放回我的活動中,我的ListView出現了奇怪的行爲:它顯示了一個空的結果。有時它只顯示一行(23)中的結果,有些時候結果不同的行顯示。當我運行應用程序 - 我大多沒有或只有一行結果。當我使用調試器時 - 我得到的所有結果都很好!怎麼來的??? - 嗯 - 我在更新我的主線程上的ListView的錯誤之前,第二個線程設法用結果更新數據庫。所以主線程從數據庫中獲取了空的結果。我也擺脫了Loop。

我的異步類現在看起來像這樣:

private class AsyncAllPlayAll extends AsyncTask<String, Void, Long> 
{ 
    Tournament mTournament = null; 

    public AsyncAllPlayAll(Tournament tournament) 
    { 
     this.mTournament = tournament; 
    } 

    @Override 
    protected Long doInBackground(String... string) 
    { 
     Long ml = null; 
     //run tournament! 
     mTournament.allPlayAll(); 

     return ml = (long) 0; 
    } 

    @Override 
    protected void onPostExecute(Long result) 
    { 
     TournamentEdit.this.runOnUiThread(new Runnable() { 

      public void run() { 
       // TODO Auto-generated method stub 
       populateCompetitorsListView(); 
      } 
     }); 
    } 
} 

正如我現在用runOnUiThread()調用我的主線程中填入方法。我仍然必須更新我的Toast消息,但是我明天會這樣做:-)

感謝您閱讀這個超長的傳奇...