对话框按钮中的 OnClickListener 被调用两次,处理时间较长

发布于 2025-01-05 08:24:24 字数 1413 浏览 1 评论 0原文

我的应用程序有一个错误,它看起来很奇怪,但很容易重现。

在活动中尝试此代码:

public    int    myIncrement = 0;

protected Dialog onCreateDialog(int i, Bundle args)
    {
        if (i == DIALOG_TEST_MY_BUG)
        {
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("Test");

            builder.setNegativeButton("Test", new DialogInterface.OnClickListener()
            {
                public void onClick(DialogInterface dialog, int id)
                {
                    Log.i("Test", "<- myIncrement : " + myIncrement);
                    for (int i = 0; i < 1000000; i++)
                        myIncrement ++;
                    Log.i("Test", "-> myIncrement : " + myIncrement);
                }
            }
        }
    }

当您显示此对话框时,就可以了。当你点击“测试”按钮时,就可以了。日志显示:

<- myIncrement : 0
-> myIncrement : 1000000

但是如果您重复单击“Test”按钮,onClickListener 将被调用 2 次或更多次:

<- myIncrement : 0
-> myIncrement : 1000000
<- myIncrement : 1000000
-> myIncrement : 2000000...

这里这个例子只是为了让您理解我的问题。相当于

                    for (int i = 0; i < 1000000; i++)
                        myIncrement ++;

一个长时间的处理,包括文件写入和视图更改,以及另一个在服务器上同步的处理。我尝试了很多更改,例如更改 onClick 方法中的布尔值,但没有成功。

请在提议之前检查您的答案。也请在您的应用程序上尝试此操作,当单击导致长时间处理时,请尝试多次单击。

I have a bug on my application, it looks really strange but it is easy to reproduce.

Try this code on an activity :

public    int    myIncrement = 0;

protected Dialog onCreateDialog(int i, Bundle args)
    {
        if (i == DIALOG_TEST_MY_BUG)
        {
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("Test");

            builder.setNegativeButton("Test", new DialogInterface.OnClickListener()
            {
                public void onClick(DialogInterface dialog, int id)
                {
                    Log.i("Test", "<- myIncrement : " + myIncrement);
                    for (int i = 0; i < 1000000; i++)
                        myIncrement ++;
                    Log.i("Test", "-> myIncrement : " + myIncrement);
                }
            }
        }
    }

When you show this dialog, it's ok. When you click on the button "Test", it's ok. The log shows :

<- myIncrement : 0
-> myIncrement : 1000000

But if you click repetitively on the button "Test", the onClickListener will be called 2 or more times :

<- myIncrement : 0
-> myIncrement : 1000000
<- myIncrement : 1000000
-> myIncrement : 2000000...

Here this exemple is just to let you understand my problem. The equivalent of

                    for (int i = 0; i < 1000000; i++)
                        myIncrement ++;

is a long processing with file writting and a view change, and an other with synchronisation on a server. I tried lots of changes, like change a boolean in the onClick method, but without success.

Please, check your answer before proposing. Please also try this on your applications, when a click causes a long processing, try to click it many times.

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

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

发布评论

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

评论(2

青春如此纠结 2025-01-12 08:24:24

您正在尝试在 UI 线程中启动一个长时间运行的任务,这是完全禁止的。如果任务运行时间超过 5 秒,它可能会导致像这样的错误和 ANR。因此,对于任何长时间运行的任务,您应该创建一个单独的线程。我建议使用 AsyncTask 类,因为它使用起来非常简单,并且与 UI 线程同步,向用户显示您的应用程序没有卡住。希望这有帮助。

You're trying to start a long running task in the UI thread, which is completely prohibited. It may cause you bugs like this and ANRs too, if the task runs longer then 5 seconds. So for any long running tasks you should create a separate thread. I'd reccomend using the AsyncTask class since it's very simple to use and to synchronize with the UI thread to show your users that your application is not stuck. Hope this helps.

秋千易 2025-01-12 08:24:24

改成这样:

private AlertDialog builder = null;
protected Dialog onCreateDialog(int i, Bundle args)
 {
     if (i == DIALOG_TEST_MY_BUG)
     {
         if(builder != null && builder.isShowing()
             return; // prevent multiple dialog instances
         builder = new AlertDialog.Builder(this);
         builder.setTitle("Test"); 

Change to this:

private AlertDialog builder = null;
protected Dialog onCreateDialog(int i, Bundle args)
 {
     if (i == DIALOG_TEST_MY_BUG)
     {
         if(builder != null && builder.isShowing()
             return; // prevent multiple dialog instances
         builder = new AlertDialog.Builder(this);
         builder.setTitle("Test"); 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文