【问题标题】:ProgressDialog doesn't show up until it's too lateProgressDialog 不显示,直到为时已晚
【发布时间】:2010-08-13 14:32:30
【问题描述】:

我正在编写一个 Activity,它通过 HTTP 从 Web 获取一些 XML,然后将其解析为 DOM。然后它从 DOM 中提取一些所需的数据。

您可以想象,这需要一些时间,所以我将该代码放入它自己的线程中,然后尝试设置一个 ProgressDialog 以在用户等待它完成时显示。

问题是 ProgressDialog 根本不显示。如果我删除对dismiss() 的调用,那么它会在工作完成后显示,并且显然只是坐在那里......

这是我的代码:

@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 时看到过一些类似的线程,但我想直接使用良好的老式线程,建议的解决方案不适用。

【问题讨论】:

    标签: android


    【解决方案1】:

    我认为问题可能与您的线程处理方式有关。当您调用 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

    【讨论】:

      【解决方案2】:

      我建议使用AsyncTask 来处理这类事情。

      【讨论】:

      • 我很想知道社区认为 AsyncTask 相对于“老派”线程的优势...
      • 有很多关于它的问题。只是链接一个:stackoverflow.com/questions/2523459/handler-vs-asynctask
      • 异步任务消除了对处理程序的所有需求,您只需执行一个快速而肮脏的匿名异步任务,该任务在后台方法中调用工作代码并在 onPostExecute 完成后调用 UI 更新无需担心哪个线程在做什么。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多