在Android上使用ProgressDialog和Thread会引发ViewRoot $ CalledWrongFromThreadException

时间:2010-12-16 19:07:36

标签: android android-progressbar

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

编辑(这是代码):

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();
    }
    }

3 个答案:

答案 0 :(得分:1)

使用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();

        }

    }

答案 1 :(得分:0)

错误必须在filterData中,如果要从过滤器数据更新UI,它将提供该异常。我建议使用异步任务,使用doInBackground构建数据,并使用onPostExecute来更新UI。

答案 2 :(得分:0)

似乎您的问题出在generateMonth函数中,该函数是从doInBackground函数调用的。您不应该从doInBackground函数或从doInBackground调用的任何函数访问UI。此函数旨在执行需要大量时间的任务,如计算或复杂的数据库查询,但绝不能访问UI。您的UI更新应该在onPostExecute函数中完成。所以,比如:

  

gridview.setNumColumns(7)

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