2011-10-10 160 views
6

我的应用程序从互联网中获取一些html代码,完成后,将其显示在设备屏幕上。由于这需要大约3-4秒的时间,因此在这段时间屏幕保持黑屏,我想使用进度对话框。这是我的代码:Android进度对话框

package com.nextlogic.golfnews; 



// ALL THE IMPORTS .... 

public class Activity1 extends Activity { 

    private ProgressDialog progressDialog; 
@Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main2); 

     progressDialog = ProgressDialog.show(Activity1.this, "", "Loading..."); 
     new Thread() 
     { 
      public void run() 
      { 

      try 
       { 
       sleep(2000); 

      // HERE I'VE PUT ALL THE FUNCTIONS THAT WORK FOR ME 
} 
    catch (Exception e) 
    { 
     Log.e("tag",e.getMessage()); 
    } 
// dismiss the progressdialog 
    progressDialog.dismiss(); 
} 
}.start(); 

该程序的工作原理,但它不再显示任何东西。我在logcat有一个错误:

Only the original thread that created a view hierarchy can touch its views. 

你能帮我吗?提前致谢。

+0

给出的答案是正确的,但我想补充一些东西。 ProgressDialogs有两种样式:STYLE_SPINNER(默认)和STYLE_HORIZONTAL。根据[ui dialogs](http://developer.android.com/guide/topics/ui/dialogs.html),我们应该遵循[进度和活动设计指南](http://developer.android.com /design/building-blocks/progress.html)并使用STYLE_HORIZONTAL(如果相关且可能的话)。在这个问题上,我发现[本教程](http://www.pavanh.com/2013/04/android-progress-dialog-example.html)非常有用。现在你可以选择你想要的ProgressDialog风格了... –

回答

17

该错误足够明确。要更新一个可视对象,您必须在主线程内运行更改。一个快速而脏的修复可能会调用runOnUiThread()内的更新代码。

但在你的情况下,我会使用AsyncTask来下载和更新进度条的进度。该任务具有在UI线程结束时运行的属性(因此您可以在其中更新视图,例如解除进度对话框)

Here是一个示例,说明如何使用AsyncTask显示下载进度对话框。

更新

#2已经拥有了你所有的问题。 Here是一个AsyncTask的例子,用于下载一些内容并显示下载进度。正是你想要的。

更新2

确定这里是使用的AsyncTask代码:

public class Activity1 extends Activity 
{ 
    private ProgressDialog progressDialog; 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     new AsyncTask<Integer, Integer, Boolean>() 
     { 
      ProgressDialog progressDialog; 

      @Override 
      protected void onPreExecute() 
      { 
       /* 
       * This is executed on UI thread before doInBackground(). It is 
       * the perfect place to show the progress dialog. 
       */ 
       progressDialog = ProgressDialog.show(Activity1.this, "", 
         "Loading..."); 
      } 

      @Override 
      protected Boolean doInBackground(Integer... params) 
      { 
       if (params == null) 
       { 
        return false; 
       } 
       try 
       { 
        /* 
        * This is run on a background thread, so we can sleep here 
        * or do whatever we want without blocking UI thread. A more 
        * advanced use would download chunks of fixed size and call 
        * publishProgress(); 
        */ 
        Thread.sleep(params[0]); 
        // HERE I'VE PUT ALL THE FUNCTIONS THAT WORK FOR ME 
       } 
       catch (Exception e) 
       { 
        Log.e("tag", e.getMessage()); 
        /* 
        * The task failed 
        */ 
        return false; 
       } 

       /* 
       * The task succeeded 
       */ 
       return true; 
      } 

      @Override 
      protected void onPostExecute(Boolean result) 
      { 
       progressDialog.dismiss(); 
       /* 
       * Update here your view objects with content from download. It 
       * is save to dismiss dialogs, update views, etc., since we are 
       * working on UI thread. 
       */ 
       AlertDialog.Builder b = new AlertDialog.Builder(Activity1.this); 
       b.setTitle(android.R.string.dialog_alert_title); 
       if (result) 
       { 
        b.setMessage("Download succeeded"); 
       } 
       else 
       { 
        b.setMessage("Download failed"); 
       } 
       b.setPositiveButton(getString(android.R.string.ok), 
         new DialogInterface.OnClickListener() 
         { 

          @Override 
          public void onClick(DialogInterface dlg, int arg1) 
          { 
           dlg.dismiss(); 
          } 
         }); 
       b.create().show(); 
      } 
     }.execute(2000); 

     new Thread() 
     { 
      @Override 
      public void run() 
      { 

       // dismiss the progressdialog 
       progressDialog.dismiss(); 
      } 
     }.start(); 
    } 
} 
+0

你能帮我吗?我是android新手,并没有完全理解这个例子。 – Teo

+0

看看更新 –

+0

事情是..我不想改变我的功能,因为该程序工作得很好,有点慢。我想把这些函数放在后台线程中,当这些函数正在执行时,我想显示进度对话框。 – Teo

1

完成网络操作

runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
      progressDialog.dismiss(); 

      } 
     }); 
4

后创建UI线程你需要做这样

runOnUiThread(new Runnable() { 
    public void run() { 
     // Do Your Stuff 
    }}); 
+0

和我在哪里解雇progressDialog? – Teo

+0

我想你只是在上面的代码中写一个函数,并且代替注释编写代码来关闭对话框,并在需要的时候调用你的任务的乐趣 – MKJParekh

2

解散你的对话是这样的:

Handler handler = new Handler(); 
handler.post(new Runnable(){ 
    public void run(){ 
     progressDialog.dismiss(); 
    } 
}); 
+0

我用你的代码替换了'progressDialog.dismiss();'。现在程序崩溃了。 – Teo

+0

放在这一行Handler handler = new Handler(); out of thread .... –

+0

我做了这个,程序崩溃了。冷杉它说:'不能在线程中创建没有调用Looper.prepare()'然后'字符串超出范围'的处理程序 – Teo