2012-08-11 20 views
9

मेरे पास एक प्रगति संवाद है जिसका उपयोग मैं अपने कार्यक्रम में एक भाग के लिए करता हूं जहां मैं पृष्ठभूमि में समय गहन ऑपरेशन करता हूं लेकिन जब संवाद प्रदर्शित होता है तो यूआई या स्पिनर आइकन फ्रीज/धीमा/हिचकिचाहट करता है कार्यक्रम के रूप में प्रकट होता है जैसे यह जम गया। मेरे AsyncTask के onPostExecute में मैंने संवाद को खारिज कर दिया।प्रगति संवाद UI फ्रीज/धीमी

ऐसा क्यों होगा क्योंकि मैं पृष्ठभूमि में सभी काम कर रहा हूं? डिबग मोड में कोड कल रात यह पाश के लिए, लेकिन अभी भी यह सब एक अलग से किया जाता है में यह करने के लिए शुरू करने के लिए लगता है के माध्यम से चल:

यहाँ मेरी कोड

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

} 

अद्यतन है थ्रेड और मैं सिर्फ अपने डेटाबेस

अद्यतन 2 अगर मैं बाहर टिप्पणी पाश के लिए प्रगति संवाद एक दूसरे से कम के लिए प्रदर्शित किया जाता तो भले ही मैं एक में सब कुछ कर रहा हूँ में मान डालने कर रहा हूँ AsyncTask इन्सर्ट अभी भी UI थ्रेड

+0

नोटिस नहीं किया था आप क्या कर रहे हैं की थी यह मुख्य धागे या यूई धागे पर है। एसओ पर इसके बारे में अन्य विषय हैं, शायद वे मदद करेंगे। http: // stackoverflow।कॉम/प्रश्न/3652560/what-is-the -roid-uithread-ui-thread –

+0

अच्छी तरह से आप देख सकते हैं कि यह एक AsyncTask है, इसलिए यह एक और थ्रेड – tyczj

+0

में होगा जहां आपका 'onPreExecute' अनुभाग है? इसके अलावा आप सभी कोड को 'doInBackground' में एक विधि में डाल सकते हैं क्योंकि इसे सभी नए धागे में निष्पादित करना चाहिए, और इसे पढ़ने के लिए यह सब आसान बनाना चाहिए। इसके अलावा आप किस हार्डवेयर पर परीक्षण कर रहे हैं? –

उत्तर

2

यह पता चल, मैं एक भगोड़ा विधि यूआई धागा चल रहा है कि मैं

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\ के तहत फ़ाइल पर जा सकते हैं और एक स्ट्रिंग को परिभाषित कर सकते हैं। फिर अपने कोड में, आप या तो getString(R.string.yourStringId) या R.string.yourStringId का उपयोग कर सकते हैं। यह निर्भर करता है कि विधि आईडी को स्वीकार करती है या नहीं (आईडी जो स्वीकार करते हैं, वास्तव में getString निष्पादित आईडी के साथ)।

+0

लेकिन अगर मैं 'onPostExecute' का उपयोग करता हूं या AsyncTask शुरू करने से पहले प्रगति संवाद की घोषणा करता हूं तो क्या अंतर है? मैं सिर्फ यह नहीं देखता कि यह समस्या को कैसे ठीक करेगा क्योंकि दोनों यूआई थ्रेड में सही हैं? – tyczj

+0

@tyczj मैं ईमानदारी से सटीक अंतर नहीं जानता (लेकिन यह कहकर, आप सवाल उठा रहे हैं कि क्यों 'onPostExecute' की आवश्यकता है)। ऐसा लगता है कि एक अंतर है, क्योंकि मुझे वही समस्या है जो आप अनुभव कर रहे हैं। मैंने AsyncTask से 'प्रोग्रेसडिअलॉग' को भी परिभाषित किया, और जब मैं अंदर चला गया, तो यह पूरी तरह से सुचारू रूप से काम करता था। मेरा सुझाव है कि आप इसे आजमाएं और देखें। इसे –

+0

पर काम करना चाहिए मैंने इसे ऑनपेक्सक्यूट में फेंक दिया और यह अभी भी वही काम करता है दुर्भाग्यवश – tyczj

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

1

ऐसा शायद होता है क्योंकि आपका पृष्ठभूमि थ्रेड 100% डिवाइस CPU का उपभोग करता है। जब सीपीयू एक थ्रेड को संसाधित करने में व्यस्त होता है, तो यूआई थ्रेड अपडेट नहीं किया जाएगा और इसलिए आप इसे

अपने डिनबैकग्राउंड से कोड के हिस्सों को हटाकर और फिर से ऐप चलाने के द्वारा सबसे आक्रामक ऑपरेशन का पता लगाने का प्रयास करें। यह भी देखें करने के लिए यह कैसा प्रदर्शन जब डिवाइस USB के माध्यम से खामियों को दूर नहीं किया गया है की कोशिश - इस कुछ समय प्रदान करता है अजीब परिणाम

+0

समस्या लूप के लिए है जहां यह मेरे डेटाबेस में फ़ील्ड डालने जा रही है। यदि मैं टिप्पणी करता हूं कि यह एक सेकंड से भी कम समय के लिए प्रगति संवाद दिखाता है, भले ही मैं 'AsyncTask' में सबकुछ कर रहा हूं, फिर भी यूआई थ्रेड में आवेषण चलाना आवश्यक है – tyczj