2010-08-13 54 views
1

我正在寫一個活動,它通過HTTP從Web獲取一些XML,然後將其解析爲一個DOM。然後它從DOM中提取一些必需的數據。ProgressDialog不會顯示,直到它太遲

您可以想象,這需要一些時間,因此我將該代碼放入它自己的線程中,然後嘗試設置ProgressDialog以在用戶等待完成時顯示。

問題是ProgressDialog根本不顯示。如果我刪除電話解僱(),那麼它顯示的工作完成之後,很明顯,只是坐在那裏......

這裏是我的代碼:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    progressDialog = ProgressDialog.show(this, "", "Loading...", true); 
    Thread downloadThread = new Thread(new DownloadVerseThread()); 
    downloadThread.start(); 
    setContentView(R.layout.main); 
    TextView verseView = (TextView) findViewById(R.id.displayFighterVerse); 
    TextView dateView = (TextView) findViewById(R.id.displayDateRange); 
    TextView referenceView = (TextView) findViewById(R.id.displayReference); 
    try { 
     downloadThread.join(); 
    } catch (InterruptedException e) { 
     Log.e(TAG, "Attempted to set the UI values before we were ready."); 
     return; 
    } 
    Log.d(TAG, "Date: " + date); 
    Log.d(TAG, "Reference: " + reference); 
    Log.d(TAG, "Scripture: " + scripture); 
    progressDialog.dismiss(); 
    dateView.setText(date); 
    referenceView.setText(reference); 
    verseView.setText(scripture); 
} 



private class DownloadVerseThread implements Runnable { 


    @Override 
    public void run() { 

     try { 
      FighterVerseDownloader downloader = new FighterVerseDownloader(); 
      date = downloader.getDateRange(); 
      reference = downloader.getReference(); 
      scripture = downloader.getScripture(); 
     } catch (FighterVersesException e) { 
      Log.e("FighterVerses", "Failed to get the Fighter Verse", e); 
     }   
    } 

} 

的FighterVersesDownloader的構造是哪裏所有關於HTTP和DOM的工作都已完成。

關於我失蹤的任何想法?我在使用AsyncTask時看到了一些類似的線程,但我想直接使用優秀的老式線程,並且建議的解決方案不適用。

回答

3

我認爲這個問題可能與你如何進行線程有關。當你調用downloadThread.join()時,你基本上會花費那些代價昂貴的代碼,並將它放在方法的中間,阻塞進程中的UI線程。

當線程完成時,您需要使用回調方法來處理UI更改。你的代碼應該是這個樣子:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    progressDialog = ProgressDialog.show(this, "", "Loading...", true); 
    Thread downloadThread = new Thread(new DownloadVerseThread()); 
    Handler downloadHandler = new Handler(); 
    Runnable downloadCallback = new Runnable(){ 
     public void run(){ 
       setContentView(R.layout.main); 
      TextView verseView = (TextView) findViewById(R.id.displayFighterVerse); 
      TextView dateView = (TextView) findViewById(R.id.displayDateRange); 
      TextView referenceView = (TextView) findViewById(R.id.displayReference); 
      Log.d(TAG, "Date: " + date); 
      Log.d(TAG, "Reference: " + reference); 
      Log.d(TAG, "Scripture: " + scripture); 
      progressDialog.dismiss(); 
      dateView.setText(date); 
      referenceView.setText(reference); 
      verseView.setText(scripture); 
     } 
    }; 
    downloadThread.start(); 
} 

private class DownloadVerseThread implements Runnable { 
    @Override 
    public void run() { 

     try { 
      FighterVerseDownloader downloader = new FighterVerseDownloader(); 
      date = downloader.getDateRange(); 
      reference = downloader.getReference(); 
      scripture = downloader.getScripture(); 
      downloadHandler.post(downloadCallback); 
     } catch (FighterVersesException e) { 
      Log.e("FighterVerses", "Failed to get the Fighter Verse", e); 
     }   
    } 
} 

這將保持在下載後臺線程,直到它完成,而不是幾乎立即分流它放回UI線程,因爲它是以前。編輯:Here's where I learned this

+0

完美 - 這是一種享受!謝謝 – 2010-08-13 15:33:14

3

我會推薦使用AsyncTask這種事情。

+0

我很想知道社區認爲AsyncTask的優點是「老派」線程的優勢... – 2010-08-13 15:33:50

+0

有很多關於它的問題。只是要鏈接一個:http://stackoverflow.com/questions/2523459/handler-vs-asynctask – Macarse 2010-08-13 15:39:23

+0

異步任務刪​​除所有需要處理程序,你可以做一個快速和骯髒的匿名異步任務調用工作代碼在後臺方法並在onPostExecute函數完成後調用UI更新,而不必擔心哪個線程在做什麼。 – Janusz 2010-08-13 16:08:58