2012-08-11 14 views
9

Mam okno dialogowe postępu, którego używam dla części w moim programie, w której wykonuję intensywną operację czasową w tle, ale kiedy okno dialogowe jest wyświetlane, ikona interfejsu użytkownika lub pokrętła zamraża/spowalnia/waha się program wygląda tak, jakby zamarł. W moim onPostExecute mojego AsyncTask odrzucam okno dialogowe.Okno dialogowe postępu UI zamarza/powolne

Dlaczego tak się stało, ponieważ wykonuję całą pracę w tle?

tutaj jest mój kod

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: działa poprzez kod w trybie debugowania ostatniej nocy wydaje się zacząć to robić w pętli for, ale nadal wszystko to odbywa się w oddzielnym wątku i mam tylko wstawianie wartości do mojej bazy danych

UPDATE 2 jeśli i ustosunkowania się do pętli zostanie wyświetlone okno dialogowe postępu na mniej niż sekundę, więc mimo że robię wszystko w sposób AsyncTask wkładki muszą nadal działać w wątku interfejsu użytkownika

+0

Robisz to na głównym wątku lub wątku interfejsu użytkownika. Są inne tematy na ten temat na SO, może oni pomogą. http: // stackoverflow.com/questions/3652560/what-is-the-android-uithread-ui-thread –

+0

Jak widać, jest to AsyncTask, więc byłoby w innym wątku – tyczj

+0

gdzie jest twoja sekcja 'onPreExecute'? Również możesz umieścić cały kod na 'doInBackground' w metodzie, jak to powinno być wykonane w nowym wątku, i uczynić to łatwiejszym do odczytania. Na jakim urządzeniu testujesz? –

Odpowiedz

2

Zdobione, miałem niespodziewany sposób dzieje wątku UI, że nie zauważył

0

Użyto błędnej wartości ProgressDialog.

Musisz dodać metodę onPreExecute i tam zdefiniować i pokazać swoją ProgressDialog. Następnie doInBackground jest wykonywany na innym wątku, a ostatecznie w onPostExecute odrzucasz okno dialogowe.

Oto prosty przykład:

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

Nawiasem mówiąc, ja też zalecamy, aby nie używać jawnie wpisanej sznurki. Zamiast tego możesz przejść do pliku strings.xml pod numerem res\values\ i zdefiniować ciąg znaków. Następnie w kodzie możesz użyć albo getString(R.string.yourStringId) lub R.string.yourStringId. Zależy od tego, czy metoda akceptuje identyfikatory, czy nie (metody, które akceptują identyfikatory, faktycznie wykonują getString za pomocą identyfikatora, który wysłałeś).

+0

Ale jaka jest różnica, jeśli używam 'onPostExecute' lub po prostu deklaruję okno postępu tuż przed uruchomieniem AsyncTask? Po prostu nie widzę, jak to rozwiązałoby problem, ponieważ oba są w wątku UI prawidłowe? – tyczj

+0

@tyczj Szczerze mówiąc, nie znam dokładnej różnicy (ale mówiąc to, powstaje pytanie, dlaczego 'onPostExecute' jest w ogóle potrzebna). Wygląda na to, że jest różnica, ponieważ miałem ten sam problem, którego doświadczasz. Zdefiniowałem również "ProgressDialog" z AsyncTask, a kiedy się wprowadziłem, działało idealnie sprawnie. Proponuję spróbować i zobaczyć. To powinno zadziałać –

+0

Wrzuciłem go do onPreExecute i nadal działało to samo niestety – tyczj

0

W ten sposób zrealizowałem dialog w ten sposób.

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

nie widzę żadnego błędu w kodzie, ale trzeba zrozumieć, że tylko pisanie kodu w innym wątku nie oznacza, że ​​będzie dostać inny procesor. jeśli twoje urządzenie ma procesor z pojedynczym rdzeniem, robi to czasowe cięcie i działa w sposób okrągły. jeśli twoje urządzenie ma wiele rdzeni, wykona rzeczywiste wielokrotne gwintowanie. więc jeśli masz procesor z pojedynczym rdzeniem, pokaże ci trochę opóźnienie w pasku postępu.

+0

wszystkie testowane urządzenia mają wiele rdzeni – tyczj

1

Prawdopodobnie dzieje się tak, ponieważ wątek tła zużywa 100% procesora urządzenia. Gdy procesor jest zajęty przetwarzaniem jednego wątku, wątek UI nie zostanie zaktualizowany i dlatego zostanie zamrożony. Spróbuj wykryć najbardziej agresywną operację, usuwając fragmenty kodu z aplikacji doInBackground i ponownie uruchamiając aplikację. Także spróbować zobaczyć jak to działa, gdy urządzenie nie jest podłączone przez USB - to kilka razy zapewnia dziwne wyniki

+0

problem dotyczy pętli for, w której wstawia pola do mojej bazy danych. Jeśli to skomentuję, pokazuje okno postępu przez mniej niż sekundę, więc najwyraźniej pomimo tego, że robię wszystko w "AsyncTask", wkładki muszą nadal działać w wątku UI – tyczj

Powiązane problemy