Android 在 PreferenceActivity 中添加 AsyncTask 首次加载大量首选项

发布于 2024-12-22 21:11:55 字数 1823 浏览 1 评论 0原文

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

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

问题是,仅允许在 UI 线程上加载首选项,因为当我尝试在异步任务中加载首选项时,我得到以下信息:

错误/AndroidRuntime(4830):原因是: android.view.ViewRoot$CalledFromWrongThreadException:仅 创建视图层次结构的原始线程可以触摸其视图。

因此,当我将 runOnUiThread() 添加到异步任务时,在 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));
}  }

我怎样才能做得更好?

I have an application with quite a lot of preferences. So when the user loads the Preferences the first time, it takes quite a while. So the UI is freezing while loading the prefs.

This is why I want to add a dialog telling the user that the prefs are loading.

The problem is, that loading the preferences is only allowed on the UI thread because when I am trying to load my preferences in the Async Task, I get this:

ERROR/AndroidRuntime(4830): Caused by:
android.view.ViewRoot$CalledFromWrongThreadException: Only the
original thread that created a view hierarchy can touch its views.

So when I add runOnUiThread() to the Async Task the whole purpose of doing it in the AsyncTask gets destroyed:

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

How can I do this better?

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

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

发布评论

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

评论(2

狂之美人 2024-12-29 21:11:55

因此,当我将 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

这样主线程将停止,并希望能够处理奇怪的行为。
再次强调:如果我还没有解决您的问题,请随时发表评论。

So when I add runOnUiThread() to the Async Task the whole purpose of
doing it in the AsyncTask gets destroyed.

I am not quite sure I understand that, but if you want to show progress dialog to the user then isn't it expected that the user will wait for the task to finish?

On the other hand if you want to load the preferences in real background task use ordinary java Thread - it is true that non-UI threads can't create AsyncTasks.

Edit: After the comment you added probably this will help you (changing part of your code in 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

That way the main thread will halt and hopefully the weird behavior will be handled.
Once again: feel free to comment if I do not solve your issue yet.

阳光下慵懒的猫 2024-12-29 21:11:55

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

如果您有一个非常大的首选项文件,则必须

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

在 UI 线程上的某个时刻调用。

我在应用程序的初始化阶段结束时执行此操作。这样,用户就不会因为应用程序的短暂冻结而感到困惑。

该命令第一次使用默认值初始化文件。之后该文件就可用并且可以相当快地访问。

I came up with the best solution that I could think of:

If you have a very big preference file you have to call

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

at some point on the UI thread.

I do this at the end of a initializing phase of the app. In that way the user is the least confused about some short freezing of the app.

This command initializes the file the first time with the default values. After that the file is available and can be accessed fairly quickly.

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