在 Android 上将 ProgressDialog 与 Thread 一起使用会引发 ViewRoot$CalledWrongFromThreadException

发布于 2024-10-08 04:06:11 字数 2650 浏览 5 评论 0原文

我试图在填充布局时显示进度对话框:

编辑(这是代码):

public class CalendarMonth extends Activity {

    private ProgressDialog mDialog;

        private int mMonth = 0;
    private int mYear = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.calendar_m);

        filterData();
    }

    private void filterData() {

        mDialog = ProgressDialog.show(this, "Loading calendar", 
                "Please wait...", true, true);
        mDialog.setCancelable(false);
        mDialog.show();

        new GenerateMonth().execute();
    }

class GenerateMonth extends AsyncTask {
        protected Object doInBackground(Object... arg0) {
            generateMonth();
            return true;
        }
        protected void onPostExecute(Object result) {
            mDialog.dismiss();
        }

    private void generateMonth() {

        mCalendar = new CalendarInstance(mMonth, mYear);

        mMonth = this.mCalendar.getSelectedMonth();
        mYear = this.mCalendar.getSelectedYear();

        TextView monthName = (TextView) findViewById(R.id.monthName);
        monthName.setText(mCalendar.getMonthAndYearAsString());

        Button monthPrevious = (Button) findViewById(R.id.monthPrevious);
        monthPrevious.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                int month = mMonth - 1;
                int year = mYear;
                if (mMonth == 1) {
                    month = 12;
                    year = mYear - 1;
                }
                mMonth = month;
                mYear = year;
                filterData();
            }
        });

        Button monthNext = (Button) findViewById(R.id.monthNext);
        monthNext.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                int month = mMonth + 1;
                int year = mYear;
                if (mMonth == 12) {
                    month = 1;
                    year = mYear + 1;
                }
                mMonth = month;
                mYear = year;
                filterData();
            }
        });

        GridView gridview = (GridView) findViewById(R.id.gridview);
        gridview.setNumColumns(7);
        gridview.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
        gridview.setBackgroundColor(Color.BLACK);
        gridview.setAdapter(new CalendarMonthAdapter(this, mMonth, mYear));     
    }

    @Override
    protected void onResume() {

        super.onResume();
        filterData();
    }
    }

I'm trying to show Progress Dialog while filling layout:

EDIT (here is the code):

public class CalendarMonth extends Activity {

    private ProgressDialog mDialog;

        private int mMonth = 0;
    private int mYear = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.calendar_m);

        filterData();
    }

    private void filterData() {

        mDialog = ProgressDialog.show(this, "Loading calendar", 
                "Please wait...", true, true);
        mDialog.setCancelable(false);
        mDialog.show();

        new GenerateMonth().execute();
    }

class GenerateMonth extends AsyncTask {
        protected Object doInBackground(Object... arg0) {
            generateMonth();
            return true;
        }
        protected void onPostExecute(Object result) {
            mDialog.dismiss();
        }

    private void generateMonth() {

        mCalendar = new CalendarInstance(mMonth, mYear);

        mMonth = this.mCalendar.getSelectedMonth();
        mYear = this.mCalendar.getSelectedYear();

        TextView monthName = (TextView) findViewById(R.id.monthName);
        monthName.setText(mCalendar.getMonthAndYearAsString());

        Button monthPrevious = (Button) findViewById(R.id.monthPrevious);
        monthPrevious.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                int month = mMonth - 1;
                int year = mYear;
                if (mMonth == 1) {
                    month = 12;
                    year = mYear - 1;
                }
                mMonth = month;
                mYear = year;
                filterData();
            }
        });

        Button monthNext = (Button) findViewById(R.id.monthNext);
        monthNext.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                int month = mMonth + 1;
                int year = mYear;
                if (mMonth == 12) {
                    month = 1;
                    year = mYear + 1;
                }
                mMonth = month;
                mYear = year;
                filterData();
            }
        });

        GridView gridview = (GridView) findViewById(R.id.gridview);
        gridview.setNumColumns(7);
        gridview.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
        gridview.setBackgroundColor(Color.BLACK);
        gridview.setAdapter(new CalendarMonthAdapter(this, mMonth, mYear));     
    }

    @Override
    protected void onResume() {

        super.onResume();
        filterData();
    }
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

相守太难 2024-10-15 04:06:11

使用 AsyncTask 可能更容易 http://developer.android.com/reference /android/os/AsyncTask.html

所以你会有类似这样的

public class Temp extends Activity {
    private Context mContext;
    private ProgressDialog mDialog

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.temp);


        mDialog = ProgressDialog.show(this, "Filter", "blah", true, true);
        mDialog.show();
        new FillDataTask.execute();

    }


    class FillDataTask extends AsyncTask {
        @Override
        protected Object doInBackground(Object... params) {

             try {
                    filterData();
                } catch (ParseException e) {
                    Log.e("FILTER", e.toString());
                    e.printStackTrace();
                }
            return true;  // you can return whatever you want here
        }

        protected void onPostExecute(Object result) {
            //update progressDialog here
            mDialog.dismiss();
        }
    }

}

编辑下面

这样做

public class CalendarMonth extends Activity {

    private ProgressDialog mDialog;

        private int mMonth = 0;
    private int mYear = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.calendar_m);

        filterData();
    }

    private void filterData() {

        mDialog = ProgressDialog.show(this, "Loading calendar", 
                "Please wait...", true, true);
        mDialog.setCancelable(false);
        mDialog.show();

        new GenerateMonth().execute();
    }

    private void genMonth()
    {

        mCalendar = new CalendarInstance(mMonth, mYear);

        mMonth = this.mCalendar.getSelectedMonth();
        mYear = this.mCalendar.getSelectedYear();

    }

    private void layoutUI()
    {
          TextView monthName = (TextView) findViewById(R.id.monthName);
        monthName.setText(mCalendar.getMonthAndYearAsString());

        Button monthPrevious = (Button) findViewById(R.id.monthPrevious);
        monthPrevious.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                int month = mMonth - 1;
                int year = mYear;
                if (mMonth == 1) {
                    month = 12;
                    year = mYear - 1;
                }
                mMonth = month;
                mYear = year;
                filterData();
            }
        });

        Button monthNext = (Button) findViewById(R.id.monthNext);
        monthNext.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                int month = mMonth + 1;
                int year = mYear;
                if (mMonth == 12) {
                    month = 1;
                    year = mYear + 1;
                }
                mMonth = month;
                mYear = year;
                filterData();
            }
        });

        GridView gridview = (GridView) findViewById(R.id.gridview);
        gridview.setNumColumns(7);
        gridview.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
        gridview.setBackgroundColor(Color.BLACK);
        gridview.setAdapter(new CalendarMonthAdapter(this, mMonth, mYear)); 
    }
}
}

class GenerateMonth extends AsyncTask {
        protected Object doInBackground(Object... arg0) {
            genMonth();
            return true;
        }
        protected void onPostExecute(Object result) {
            layoutUI();
            mDialog.dismiss();

        }

    }

it might be easier to use an AsyncTask http://developer.android.com/reference/android/os/AsyncTask.html

so you would have something like this

public class Temp extends Activity {
    private Context mContext;
    private ProgressDialog mDialog

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.temp);


        mDialog = ProgressDialog.show(this, "Filter", "blah", true, true);
        mDialog.show();
        new FillDataTask.execute();

    }


    class FillDataTask extends AsyncTask {
        @Override
        protected Object doInBackground(Object... params) {

             try {
                    filterData();
                } catch (ParseException e) {
                    Log.e("FILTER", e.toString());
                    e.printStackTrace();
                }
            return true;  // you can return whatever you want here
        }

        protected void onPostExecute(Object result) {
            //update progressDialog here
            mDialog.dismiss();
        }
    }

}

EDIT BELOW

do it like this

public class CalendarMonth extends Activity {

    private ProgressDialog mDialog;

        private int mMonth = 0;
    private int mYear = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.calendar_m);

        filterData();
    }

    private void filterData() {

        mDialog = ProgressDialog.show(this, "Loading calendar", 
                "Please wait...", true, true);
        mDialog.setCancelable(false);
        mDialog.show();

        new GenerateMonth().execute();
    }

    private void genMonth()
    {

        mCalendar = new CalendarInstance(mMonth, mYear);

        mMonth = this.mCalendar.getSelectedMonth();
        mYear = this.mCalendar.getSelectedYear();

    }

    private void layoutUI()
    {
          TextView monthName = (TextView) findViewById(R.id.monthName);
        monthName.setText(mCalendar.getMonthAndYearAsString());

        Button monthPrevious = (Button) findViewById(R.id.monthPrevious);
        monthPrevious.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                int month = mMonth - 1;
                int year = mYear;
                if (mMonth == 1) {
                    month = 12;
                    year = mYear - 1;
                }
                mMonth = month;
                mYear = year;
                filterData();
            }
        });

        Button monthNext = (Button) findViewById(R.id.monthNext);
        monthNext.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                int month = mMonth + 1;
                int year = mYear;
                if (mMonth == 12) {
                    month = 1;
                    year = mYear + 1;
                }
                mMonth = month;
                mYear = year;
                filterData();
            }
        });

        GridView gridview = (GridView) findViewById(R.id.gridview);
        gridview.setNumColumns(7);
        gridview.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
        gridview.setBackgroundColor(Color.BLACK);
        gridview.setAdapter(new CalendarMonthAdapter(this, mMonth, mYear)); 
    }
}
}

class GenerateMonth extends AsyncTask {
        protected Object doInBackground(Object... arg0) {
            genMonth();
            return true;
        }
        protected void onPostExecute(Object result) {
            layoutUI();
            mDialog.dismiss();

        }

    }
狼性发作 2024-10-15 04:06:11

该错误必须出现在filterData 中,如果您从过滤器数据更新UI,则会出现该异常。我建议使用异步任务,使用 doInBackground 构建数据,并使用 onPostExecute 更新 UI。

The error must be in filterData, if you are updating the UI from filter data it will give that exception. I would recomend using async task, using doInBackground to build the data, and onPostExecute to update the UI.

多情出卖 2024-10-15 04:06:11

看来您的问题出在generateMonth函数中,该函数是从doInBackground函数调用的。您不应该从 doInBackground 函数或从 doInBackground 调用的任何函数访问 UI。此函数旨在执行需要大量时间的任务,例如计算或复杂的数据库查询,但不得访问 UI。您的 UI 更新应在 onPostExecute 函数中完成。所以,像这样的事情:

gridview.setNumColumns(7)

doInBackground(或从那里调用的generateMonth)中不允许使用

It seems that your problem is in generateMonth function, which is invoked from the doInBackground function. You should not access UI from doInBackground function or from any function called from doInBackground. This function is aimed to do tasks that require lot of time, like calculations or complex DB queries, but MUST NOT access UI. Your UI updates should be done in function onPostExecute. So, things like:

gridview.setNumColumns(7)

are not allowed in doInBackground (or generateMonth which is invoked from there).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文