2010-08-13 56 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