Android将AsyncTask添加到PreferenceActivity以首次加载大量首选项

时间:2011-12-24 13:21:48

标签: android android-asynctask progressdialog preferenceactivity

我有一个有很多偏好的应用程序。因此,当用户第一次加载首选项时,需要很长时间。因此在加载prefs时UI会冻结。

这就是为什么我想添加一个对话框,告诉用户prefs正在加载。

问题是,加载首选项只允许在UI线程上,因为当我尝试在异步任务中加载我的首选项时,我得到了这个:

  

错误/ AndroidRuntime(4830):引起:   android.view.ViewRoot $ CalledFromWrongThreadException:只有   创建视图层次结构的原始线程可以触及其视图。

因此,当我将runOnUiThread()添加到Async Task时,在AsyncTask中执行它的全部目的都会被破坏:

public class ApplicationPreferences extends PreferenceActivity {


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

    new ProgressTask(ApplicationPreferences.this).execute();
}

private class ProgressTask extends AsyncTask<Void, Void, Void> {

    private Context context;

    private ProgressDialog dialog;

    public ProgressTask(ListActivity activity) {
        context = activity;
        dialog = new ProgressDialog(context);
    }

    protected void onPreExecute() {
        this.dialog.setMessage("Loading...");
        this.dialog.show();
    }

    @Override
    protected Void doInBackground(Void... params) {
        runOnUiThread(new Runnable() {

            @Override
            public void run() {

                initPreferences();

            }
        });

        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        if (dialog.isShowing()) {
            dialog.dismiss();
        }
    }

}

/*
* THIS TAKES LONG THE FIRST TIME
*/
private void initPreferences() {


    addPreferencesFromResource(R.xml.preferences);

    // preferences
    ListPreference pref1 = (ListPreference) findPreference(getString(R.string.pref1));

    // ........ etc


}




public static void start(Context context) {
    context.startActivity(new Intent(context, ApplicationPreferences.class));
}  }

我怎样才能更好地做到这一点?

2 个答案:

答案 0 :(得分:0)

  

所以当我将runOnUiThread()添加到异步任务的整个目的时   在AsyncTask中执行它会被破坏。

我不太清楚我理解这一点,但是如果你想向用户显示进度对话框,那么用户是否会等待任务完成?

另一方面,如果你想在真实的后台任务中加载首选项,请使用普通的java线程 - 非UI线程确实无法创建AsyncTasks。

修改:在您添加的评论之后,这可能会对您有所帮助(在ApplicationPreferences#onCreate中更改部分代码):

ProgressTask pTask = new ProgressTask(ApplicationPreferences.this);
pTask.execute();
// Wait for the async task to finish the specified amount of time.
pTask.get(10, TimeUnit.SECONDS); // Choose appropriate timeframe

这样主线程就会停止,希望能处理奇怪的行为。
再一次:如果我还没有解决你的问题,请随时发表评论。

答案 1 :(得分:0)

我提出了我能想到的最佳解决方案:

如果您有一个非常大的偏好文件,则必须致电

PreferenceManager.setDefaultValues(context, R.xml.mypreferencefile, false);

在UI线程上的某个时刻。

我是在应用初始化阶段结束时这样做的。通过这种方式,用户对应用程序的一些短暂冻结最不安。

此命令首次使用默认值初始化文件。之后,该文件可用,并且可以非常快速地访问。