PreferenceActivity 中的 Toast 显示较晚

发布于 2024-09-16 18:50:45 字数 632 浏览 10 评论 0原文

我想在用户单击 PreferenceActivity 中的 CheckBoxPreference 后立即显示 Toast。

myCheckBox.setOnPreferenceClickListener(new OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {
                Toast.makeText(Prefs.this,
                        "test",
                        Toast.LENGTH_SHORT).show();
                doSomething();
                return false;
            }
        });

我还尝试将 Toast 放入 doSomething() 方法中,但它总是在整个方法处理完之后显示。我尝试使用 getBaseContext() 而不是 Prefs.this,但没有帮助。 知道为什么 Toast 没有立即显示以及如何让它显示吗?

I want to show a Toast right after the user clicks on a CheckBoxPreference in my PreferenceActivity.

myCheckBox.setOnPreferenceClickListener(new OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {
                Toast.makeText(Prefs.this,
                        "test",
                        Toast.LENGTH_SHORT).show();
                doSomething();
                return false;
            }
        });

I also tried to put the Toast into the doSomething() method, but it's always shown after the whole method is processed. I tried getBaseContext() instead of Prefs.this, but it didn't help.
Any idea why the Toast doesn't show up at once and how to make it do so?

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

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

发布评论

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

评论(2

西瓜 2024-09-23 18:50:45

发生这种情况是因为 onPreferenceClick 侦听器正在 UI 线程中运行。该线程也与处理显示 Toast 的线程相同。 Toast#show 仅将消息推送到消息队列,然后运行代码以使 Toast 显示。在 onPreferenceClick 处理程序完全完成之后才会处理该队列。

您可以尝试:

myCheckBox.setOnPreferenceClickListener(new OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {
                Toast.makeText(Prefs.this,
                        "test",
                        Toast.LENGTH_SHORT).show();

                Prefs.this.runOnUiThread(new Runnable() {
                    @Override
                        public void run() {
                            doSomething();
                        }
                    });
                return false;
            }
    });

这将导致 Toast 发布到消息队列,然后您的 doSomething 也会在 toast 后发布到队列。这样做的缺点是,在调用 doSomething 之前可能会处理一些 UI 消息。此外,如果 doSomething 长时间运行,它将独占您的 UI 线程,并可能导致可能的 ANR 强制关闭。您可能需要考虑在 < 中运行 doSomething code>AsyncTask 如果需要超过 150ms 左右。

This is happening because the onPreferenceClick listener is running in the UI thread. This thread is also the same as the one that handles displaying the Toast. Toast#show only pushes a message onto the message queue that will then run code to make the Toast display. That queue won't be processed until after your onPreferenceClick handler is completely finished.

You can try:

myCheckBox.setOnPreferenceClickListener(new OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {
                Toast.makeText(Prefs.this,
                        "test",
                        Toast.LENGTH_SHORT).show();

                Prefs.this.runOnUiThread(new Runnable() {
                    @Override
                        public void run() {
                            doSomething();
                        }
                    });
                return false;
            }
    });

This will cause the Toast to post to the message queue then your doSomething will also be posted to the queue after the toast. The downside to this is that there could be UI messages that will be handled before doSomething is called. Also, if doSomething is long running it will monopolize your UI thread and could cause a possible ANR force close. You may want to think about running doSomething in an AsyncTask if it takes more than 150ms or so.

噩梦成真你也成魔 2024-09-23 18:50:45

我的解决方案是使用广播,并在 android 清单中注册一个接收器。

在 AndroidManifest 中:

    <receiver android:name=".MyReceiver" >
        <intent-filter >
            <action android:name="showtoast" />
        </intent-filter>
    </receiver>

发送广播:

public static void BroadcastMessage(Context context, Bundle extra)
{
    Intent intent = new Intent();
    intent.setPackage(context.getPackageName());
    intent.setAction("showtoast");
    if (extra != null)
        intent.putExtras(extra);
    context.sendBroadcast(intent);
}

接收器如下所示:

public class MyReceiver extends BroadcastReceiver {

    public void onReceive(Context context, Intent intent) {
        Bundle bundle = intent.getExtras();
        if ("showtoast".equalsIgnoreCase(intent.getAction()) && (bundle != null)
        {
            String title = bundle.getString("title", "");

            View view;
            TextView mTextView;
            LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.my_toast_layout, null);
            mTextView = (TextView) view.findViewById(R.id.tv_title);
            mTextView.setText(title);

            Toast toast = new Toast(context.getApplicationContext());
            toast.setGravity(Gravity.CENTER, 0, 0);
            toast.setView(view);
            toast.setDuration(Toast.LENGTH_LONG);
            toast.show();
        }
    }
}

My solution is use broadcast, and make a receiver registered in android manifest.

in AndroidManifest:

    <receiver android:name=".MyReceiver" >
        <intent-filter >
            <action android:name="showtoast" />
        </intent-filter>
    </receiver>

sending broadcast:

public static void BroadcastMessage(Context context, Bundle extra)
{
    Intent intent = new Intent();
    intent.setPackage(context.getPackageName());
    intent.setAction("showtoast");
    if (extra != null)
        intent.putExtras(extra);
    context.sendBroadcast(intent);
}

receiver like below:

public class MyReceiver extends BroadcastReceiver {

    public void onReceive(Context context, Intent intent) {
        Bundle bundle = intent.getExtras();
        if ("showtoast".equalsIgnoreCase(intent.getAction()) && (bundle != null)
        {
            String title = bundle.getString("title", "");

            View view;
            TextView mTextView;
            LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.my_toast_layout, null);
            mTextView = (TextView) view.findViewById(R.id.tv_title);
            mTextView.setText(title);

            Toast toast = new Toast(context.getApplicationContext());
            toast.setGravity(Gravity.CENTER, 0, 0);
            toast.setView(view);
            toast.setDuration(Toast.LENGTH_LONG);
            toast.show();
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文