【问题标题】:In android Why my ProgressBar Freezes?在 android 为什么我的 ProgressBar 冻结?
【发布时间】:2011-11-30 07:07:32
【问题描述】:

我在从服务器检索数据时显示进度条,在从服务器检索数据后在图表上显示该数据但在图表上绘制该数据时,我的进度条冻结有没有人知道为什么会这样。 .....

提前致谢……

private ProgressDialog pd;
private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {        
        Toast.makeText(context, "Please Wait...", Toast.LENGTH_LONG).show();
        Thread t = new Thread(new Runnable() {              
            @Override
            public void run() {
                functionDrawMyData();/*in this function i am accessing activity view and drawing data on that view at time of drawing my Progress bar Freezes */
            }
        });
        runOnUiThread(t);
        pd.dismiss();           
    }
};  

我正在使用的这个处理程序在检索数据完成后被调用 并单击按钮,我正在获取数据并显示进度条

ImageButton myButton = (ImageButton) findViewById(R.id.myBtn);
pair1ChartButton.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {               
                pd = ProgressDialog.show(v.getContext(),"Please wait...","Retrieving data ...",true,
                        true,
                        new DialogInterface.OnCancelListener(){
                            @Override
                            public void onCancel(DialogInterface dialog) {

                            }
                        });
                Thread t = new Thread(new Runnable() {                      
                    @Override
                    public void run() {
                            getDataFromServer();//calling function to get data from server
                        handler.sendEmptyMessage(0);                    
                    }
                });
                t.start();
        }
    });

【问题讨论】:

    标签: android progress-bar


    【解决方案1】:

    记住 android 将 dilogs 的引用保存在内存中。这样它就不需要一次又一次地重新创建它。所以进度对话框第一次工作正常,但下次挂起/卡住。

    注意: android 不会清除 dilogs 的内存引用,即使在解除它们之后也是如此。

    有一个方法是Activity 类命名为removeDialog(int id) 这也会清除内存引用。

    这是显示和删除对话框的方法

    protected Dialog onCreateDialog(int id) {
            // TODO Auto-generated method stub
            switch(id){
              case 0:{
                 dialog = ProgressDialog.show(this, "", 
                        "Loading. Please wait...", true);
                 return dialog;
              }
                 }
    
            return super.onCreateDialog(id);
        }
    

    现在只需调用showDialog(0) 显示对话框并调用removeDialog(0) 隐藏它。

    【讨论】:

    • 这应该是公认的答案。不过应该注意的是,ProgressDialog 已被弃用,应该避免使用。
    【解决方案2】:

    你应该在AsyncTask(一个智能后台线程)和ProgressDialog的帮助下做到这一点

    AsyncTask 允许正确且轻松地使用 UI 线程。此类允许在 UI 线程上执行后台操作并发布结果,而无需操作线程和/或处理程序。

    异步任务由在后台线程上运行的计算定义,其结果在 UI 线程上发布。异步任务由 3 种通用类型定义,称为 Params、Progress 和 Result,以及 4 个步骤,称为 begin、doInBackground、processProgress 和 end。

    四个步骤

    当一个异步任务被执行时,任务会经过4个步骤:

    onPreExecute(),在任务执行后立即在 UI 线程上调用。此步骤通常用于设置任务,例如通过在用户界面中显示进度条。

    doInBackground(Params...),在 onPreExecute() 执行完成后立即在后台线程上调用。此步骤用于执行可能需要很长时间的后台计算。异步任务的参数传递到这一步。计算的结果必须由这一步返回,并将传递回最后一步。此步骤还可以使用 publishProgress(Progress...) 来发布一个或多个进度单位。这些值在 UI 线程的 onProgressUpdate(Progress...) 步骤中发布。

    onProgressUpdate(Progress...),在调用 publishProgress(Progress...) 后在 UI 线程上调用。执行的时间是不确定的。此方法用于在后台计算仍在执行时在用户界面中显示任何形式的进度。例如,它可用于动画进度条或在文本字段中显示日志。

    onPostExecute(Result),在后台计算完成后在 UI 线程上调用。后台计算的结果作为参数传递给该步骤。 线程规则

    要使此类正常工作,必须遵循一些线程规则:

    任务实例必须在 UI 线程上创建。 必须在 UI 线程上调用 execute(Params...)。 不要手动调用 onPreExecute()、onPostExecute(Result)、doInBackground(Params...)、onProgressUpdate(Progress...)。 该任务只能执行一次(如果尝试第二次执行将引发异常。)

    示例代码
    适配器在这个例子中做了什么并不重要,更重要的是要了解您需要使用 AsyncTask 来显示进度对话框。

    private class PrepareAdapter1 extends AsyncTask<Void,Void,ContactsListCursorAdapter > {
        ProgressDialog dialog;
        @Override
        protected void onPreExecute() {
            dialog = new ProgressDialog(viewContacts.this);
            dialog.setMessage(getString(R.string.please_wait_while_loading));
            dialog.setIndeterminate(true);
            dialog.setCancelable(false);
            dialog.show();
        }
        /* (non-Javadoc)
         * @see android.os.AsyncTask#doInBackground(Params[])
         */
        @Override
        protected ContactsListCursorAdapter doInBackground(Void... params) {
            cur1 = objItem.getContacts();
            startManagingCursor(cur1);
    
            adapter1 = new ContactsListCursorAdapter (viewContacts.this,
                    R.layout.contact_for_listitem, cur1, new String[] {}, new int[] {});
    
            return adapter1;
        }
    
        protected void onPostExecute(ContactsListCursorAdapter result) {
            list.setAdapter(result);
            dialog.dismiss();
        }
    }
    

    【讨论】:

    • 我如何在这个 AsyncTask 子类中访问我的活动视图
    • 我没有得到 preExecute() 中的 viewContacts 是什么
    • 它是父类名,保存着这里发布的私有类。
    • 但我遇到以下问题无法在未调用 Looper.prepare() 的线程内创建处理程序
    • 我正在从该类之外的 doInBackground 调用一个函数,并且在该函数中,我在超出错误之后向线性布局添加了一些视图
    【解决方案3】:

    这是因为您甚至在关闭或关闭对话框之前就开始更新 UI。这是您的 progressDialog 冻结的原因。

    所以像这样改变你的代码,

         pd.dismiss();  
        runOnUiThread(t);
    

    【讨论】:

    • 那么你必须在调用 runOnUiThread(t) 之前关闭旧对话框并启动一个新的进度对话框。
    【解决方案4】:

    我也遇到过同样的问题,我自己解决了,

    请看我的示例代码。你会明白的。

    public class NearByLoc extends AsyncTask<Void, Void, Void> {
        @SuppressLint("InlinedApi")
        protected void onPreExecute() {
    
            // pdailog.show();
            loading_spinnerMain.setVisibility(View.VISIBLE);
        }
    
    
    @Override
        protected Void doInBackground(Void... params) {
         //write your entire code [logic]here
    
      }
    @Override
        protected void onPostExecute(Void unused) {
    
            //finally list of data setting to the adapter
            //before setting to the adapter you should dismiss Progress spinnerr 
    
            loading_spinnerMain.setVisibility(View.GONE);
            NearByMeAdapter adapter = new NearByMeAdapter(NearByMe.this, list);
    
            listViewNearLoc.setAdapter(adapter);
    }
    

    它对我有用..希望它可以帮助你

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多