2012-08-11 55 views
9

我有一個進度對話框,我用於我的程序中的一部分,我在後臺進行時間密集型操作,但是當對話框顯示時,UI或微調器圖標凍結/慢/猶豫該程序看起來好像凍結了。在我的AsyncTaskonPostExecute中,我忽略了該對話框。進度對話框用戶界面凍結/慢

爲什麼會發生這種情況,因爲我在後臺完成所有工作?

這裏是我的代碼

pDialog = ProgressDialog.show(FullGame.this,"Starting New Game","Please Wait...", true); 
new StartNewGame().execute(); 

    private class StartNewGame extends AsyncTask<Void,Void,Boolean>{ 

    @Override 
    protected Boolean doInBackground(Void... params) { 
     try{ 
      ContentValues values = new ContentValues(); 
      Cursor c = getContentResolver().query(Games.PART1_URI,new String[] {Games.PART1_NUM}, 
        Games.PART1_GAME_ID+"="+gameID+" AND "+Games.PART1_FRAME_NUM+"="+10,null,null); 
      c.moveToFirst(); 
      String num = c.getString(0); 
      int part1 =0; 
      if(num.equals("-")){ 
       part1=0; 
      }else{ 
       part1=Integer.parseInt(num); 
      } 

      c = getContentResolver().query(Games.PART2_URI,new String[] {Games.PART2_NUM}, 
        Games.PART2_GAME_ID+"="+gameID+" AND "+Games.PART2_FRAME_NUM+"="+10,null,null); 
      c.moveToFirst(); 
      int part2 = 0; 
      if(num.equals("-")){ 
       part2=0; 
      }else{ 
       part2=Integer.parseInt(num); 
      } 

      c = getContentResolver().query(Games.PART3_URI,new String[] {Games.PART3_NUM}, 
        Games.PART3_GAME_ID+"="+gameID,null,null); 
      c.moveToFirst(); 
      int part3 = 0; 
      if(num.equals("-")){ 
       part3=0; 
      }else{ 
       part3=Integer.parseInt(num); 
      } 

      if(part1 == 10){ 
       values.clear(); 
       values.put(Games.STRIKES_FRAME_NUM,10); 
       values.put(Games.STRIKES_BOWLER_ID,bowlerClickedID); 
       values.put(Games.STRIKES_GAME_ID,gameID); 
       getContentResolver().insert(Games.STRIKES_URI, values); 
      } 
      if(part2 == 10){ 
       values.clear(); 
       values.put(Games.STRIKES_FRAME_NUM,10); 
       values.put(Games.STRIKES_BOWLER_ID,bowlerClickedID); 
       values.put(Games.STRIKES_GAME_ID,gameID); 
       getContentResolver().insert(Games.STRIKES_URI, values); 
      } 
      if(((part2+part3) == 10) && !score.checkSpare(10)){ 
       values.clear(); 
       values.put(Games.SPARES_BOWLER_ID,bowlerClickedID); 
       values.put(Games.SPARES_FRAME_NUM,10); 
       values.put(Games.SPARES_GAME_ID,gameID); 
       getContentResolver().insert(Games.SPARES_URI, values); 
      } 
      if(part3 == 10){ 
       values.clear(); 
       values.put(Games.STRIKES_FRAME_NUM,10); 
       values.put(Games.STRIKES_BOWLER_ID,bowlerClickedID); 
       values.put(Games.STRIKES_GAME_ID,gameID); 
       getContentResolver().insert(Games.STRIKES_URI, values); 
      } 
     c.close(); 
     }catch(Exception e){ 
      Log.d("FullGame",e.toString()); 
     } 

     Date date = new Date(System.currentTimeMillis()); 
     DateFormat df = new SimpleDateFormat("MM/dd/yyyy"); 
     String newDate = df.format(date); 

     ContentValues values = new ContentValues(); 
     values.put(Games.GAMES_BOWLER_ID,bowlerClickedID); 
     values.put(Games.GAMES_TEAM_ID,1); 
     values.put(Games.GAMES_DATE,newDate); 
     values.put(Games.GAME_SEASON, pref.getLong(Preferences.SELECTED_SEASON, 1)); 
     values.put(Games.GAMES_TOURNAMENT_ID, tournamentID); 
     Uri uri = getContentResolver().insert(Games.GAMES_URI, values); 
     gameID = ContentUris.parseId(uri); 
     int gameid = Integer.valueOf(String.valueOf(gameID)); 
     values.clear(); 
     Cursor cName = getContentResolver().query(BowlersDB.CONTENT_URI,new String[] {BowlersDB.FIRST_NAME},BowlersDB.ID+"="+bowlerClickedID,null,null); 
     cName.moveToFirst(); 
     String name = cName.getString(0); 
     for(int i = 0;i<10;i++){ 
      int num = i+1; 
      values.put(Games.NAMES_FRAME_NUM,num); 
      values.put(Games.NAMES_GAME_ID,gameid); 
      values.put(Games.NAMES_NAME,name); 
      getContentResolver().insert(Games.NAMES_URI, values); 
      names(i,name); 
      values.clear(); 
      values.put(Games.PART1_FRAME_NUM,num); 
      values.put(Games.PART1_NUM,"0"); 
      values.put(Games.PART1_GAME_ID,gameid); 
      getContentResolver().insert(Games.PART1_URI, values); 
      values.clear(); 
      values.put(Games.PART2_FRAME_NUM,num); 
      values.put(Games.PART2_NUM,"0"); 
      values.put(Games.PART2_GAME_ID,gameid); 
      getContentResolver().insert(Games.PART2_URI, values); 
      values.clear(); 
      values.put(Games.TOTALS_FRAME_NUM,num); 
      values.put(Games.TOTALS_FRAME_TOTAL,"0"); 
      values.put(Games.TOTALS_GAME_ID,gameid); 
      getContentResolver().insert(Games.TOTALS_URI, values); 
      values.clear(); 
      values.put(Games.POCKETS_BOWLER_ID,bowlerClickedID); 
      values.put(Games.POCKETS_FRAME_NUM,i); 
      values.put(Games.POCKETS_GAME_ID,gameID); 
      values.put(Games.POCKETS_TEAM_ID, teamSelectedID); 
      values.put(Games.POCKETS_TOURNAMENT_ID, tournamentID); 
      values.put(Games.POCKETS_NUM, 0); 
      values.put(Games.POCKETS_SEASON, pref.getLong(Preferences.SELECTED_SEASON, 1)); 
      getContentResolver().insert(Games.POCKETS_URI, values); 
      values.clear(); 
     } 

     values.put(Games.PART3_GAME_ID,gameid); 
     values.put(Games.PART3_NUM,"0"); 
     getContentResolver().insert(Games.PART3_URI, values); 
     cName.close(); 
     part1Array = new int[10]; 
     part2Array = new int[10]; 
     totalsArray = new int[10]; 
     part3 = 0; 
     mPinsUp = new ArrayList<Long>(); 
     mPinsUp.add((long) 1); 
     mPinsUp.add((long) 2); 
     mPinsUp.add((long) 3); 
     mPinsUp.add((long) 4); 
     mPinsUp.add((long) 5); 
     mPinsUp.add((long) 6); 
     mPinsUp.add((long) 7); 
     mPinsUp.add((long) 8); 
     mPinsUp.add((long) 9); 
     mPinsUp.add((long) 10); 
     return true; 
    } 

    protected void onPostExecute(Boolean result){ 
      pDialog.dismiss(); 
    } 

} 

UPDATE: 通過昨晚在調試模式下的代碼,它似乎開始做它在for循環,但仍所有這一切都在一個單獨的完成運行線程,我只是值插入我的數據庫

更新2 如果我註釋掉for循環的進度對話框被顯示不到一秒鐘,這樣即使我在做的一切AsyncTask插入必須仍然在UI線程中運行

+0

你在做這在主線程或ui線程上。還有關於這個的其他話題,也許他們會幫助。 HTTP://計算器。com/questions/3652560/what-is-android-uithread-ui-thread – 2012-08-13 13:12:16

+0

以及你可以看到它是一個AsyncTask,所以它會在另一個線程 – tyczj 2012-08-13 14:50:55

+0

你的'onPreExecute'部分在哪裏?你也可以將'doInBackground'中的所有代碼放入一個方法中,因爲它應該全部在新線程中執行,並使所有這些更容易閱讀。您還測試了哪些硬件? – 2012-08-13 15:00:47

回答

2

想通了,我已經失控的方法會在UI線程上,我沒有注意到

0

您正在使用ProgressDialog錯誤。

您需要添加onPreExecute方法,並在那裏定義並顯示您的ProgressDialog。然後在另一個線程上執行doInBackground,最後在onPostExecute中關閉對話框。

這裏有一個簡單的例子:

class RefreshChanges extends AsyncTask<String, Void, String> { 
     private ProgressDialog mProgressDialog = new ProgressDialog(
       mContext); 

     @Override 
     protected void onPreExecute() { 
      mProgressDialog.setTitle("Whatever title"); 
      mProgressDialog.setMessage("Whatever message"); 
      mProgressDialog.show(); 
     } 

     protected String doInBackground(String... strings) { 
      // Do whatever processing you want... 
      return ""; 
     } 

     protected void onPostExecute(String result) { 
      mProgressDialog.dismiss(); 
      mProgressDialog = null; 
     } 
    } 
    new RefreshChanges().execute(); 

順便說一句,我還建議你不要使用硬編碼字符串。相反,您可以轉到res\values\下的strings.xml文件並定義一個字符串。然後在您的代碼中,您可以使用getString(R.string.yourStringId)R.string.yourStringId。它取決於該方法是否接受Id的方法(接受Id的方法,實際執行getString與你發送的Id)。

+0

但是,如果我在啓動AsyncTask之前使用'onPostExecute'或者只是聲明進度對話框,那麼它有什麼區別?我只是不知道如何解決這個問題,因爲兩者都在UI線程中是正確的? – tyczj 2012-08-14 17:16:12

+0

@tyczj我真的不知道確切的區別(但是通過說出這個問題,你就提出了爲什麼需要'onPostExecute'這個問題)。 看起來有區別,因爲我遇到了同樣的問題。我還從AsyncTask中定義了'ProgressDialog',當我進入它時,它工作得非常順利。我建議你試試看。它應該工作 – 2012-08-14 17:37:32

+0

我把它扔在onPreExecute,它仍然做了不幸的 – tyczj 2012-08-14 22:02:01

0

我已經用這種方式成功實現了對話框。

private ProgressDialog progress; 

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

     @Override 
     protected void onPreExecute() { 
      progress = ProgressDialog.show(context, "", "Please wait...", true); 

     } 

     @Override 
     protected void onPostExecute(Void params) { 
      if (progress.isShowing()) 
        progress.dismiss(); 

     } 

     @Override 
     protected Void doInBackground(Void... arg0) { 
      // Do some work 
      return null; 
     } 
} 
0

我看不出有任何故障代碼,但你要明白,只有在另一個線程編寫代碼並不意味着它會得到另一個處理器。如果您的設備使用單核心處理器,它可以進行時間分片並以循環方式工作。如果您的設備具有多個內核,則它將執行實際的多重線程。所以如果你有單核心處理器,它會向你展示一些滯後的進度條。

+0

所有測試的設備都具有多核心 – tyczj 2012-08-16 14:14:55

1

這可能是因爲您的後臺線程佔用100%的設備CPU。當CPU忙於處理一個線程時,UI線程將不會更新,因此您將其視爲凍結

嘗試通過從doInBackground中刪除部分代碼並再次運行應用程序來檢測最積極的操作。也可以嘗試,看看它如何執行時,設備沒有通過USB插入 - 這有時提供了奇怪的結果

+0

問題是在for循環它插入字段到我的數據庫。如果我評論說,它顯示進度對話框不到一秒鐘,所以顯然即使我正在做一切'AsyncTask'插入必須仍然在UI線程中運行 – tyczj 2012-08-16 22:51:55