Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion Button#onClickListener thread unsafe?

Received: by 10.204.6.19 with SMTP id 19mr613009bkx.8.1350233500735;
        Sun, 14 Oct 2012 09:51:40 -0700 (PDT)
X-BeenThere: android-developers@googlegroups.com
Received: by 10.204.131.72 with SMTP id w8ls4315496bks.3.gmail; Sun, 14 Oct
 2012 09:48:47 -0700 (PDT)
Received: by 10.204.5.194 with SMTP id 2mr611391bkw.7.1350233327332;
        Sun, 14 Oct 2012 09:48:47 -0700 (PDT)
Received: by 10.204.5.194 with SMTP id 2mr611390bkw.7.1350233327314;
        Sun, 14 Oct 2012 09:48:47 -0700 (PDT)
Return-Path: <jg.sv...@gmail.com>
Received: from mail-lb0-f196.google.com (mail-lb0-f196.google.com [209.85.217.196])
        by gmr-mx.google.com with ESMTPS id y23si100050bkv.2.2012.10.14.09.48.47
        (version=TLSv1/SSLv3 cipher=OTHER);
        Sun, 14 Oct 2012 09:48:47 -0700 (PDT)
Received-SPF: pass (google.com: domain of jg.sv...@gmail.com designates 209.85.217.196 as permitted sender) client-ip=209.85.217.196;
Authentication-Results: gmr-mx.google.com; spf=pass (google.com: domain of jg.sv...@gmail.com designates 209.85.217.196 as permitted sender) smtp.mail=jg.sv...@gmail.com; dkim=pass header...@gmail.com
Received: by mail-lb0-f196.google.com with SMTP id n8so1053056lbj.3
        for <android-developers@googlegroups.com>; Sun, 14 Oct 2012 09:48:47 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20120113;
        h=mime-version:in-reply-to:references:from:date:message-id:subject:to
         :content-type;
        bh=7cbuz0vxy2xqcO4Bb51XVHzGYrTCskuvNccDGLrzrp8=;
        b=0LaJ2Xoq9ZsnHai5GPnTv/0+RxUO2EnXaBfbD9tV2tsdi6FHsy7I7xPwHrlTkBbVe2
         3PNPXHSLEuo+hhx91FwKvIpfeU1+q5OU4I6EUQewDRlwulUZLUpbl4yl/HLjCNoGXn2P
         ApoNXi7ZSQ2+ogvPlmAteL1MLu//+rdcrlSfy5K+qibeSMUYTzULtC+dZDKQn4TjXED4
         4Yxy0HIXKfS/2A3NxNinRdy9keQHyLHXjI7DbG/aZwbCmZaT9ImOvv4/54ulI1UYbMJq
         TYsUH34UCF3qN5Ta94+NmTst4Kz+yMFiCxiz29Ry9TXuOGZyw8S6V1kmMlbg2yb+Jdsu
         FZqg==
Received: by 10.152.105.103 with SMTP id gl7mr8008231lab.10.1350233326915;
 Sun, 14 Oct 2012 09:48:46 -0700 (PDT)
MIME-Version: 1.0
Received: by 10.112.4.38 with HTTP; Sun, 14 Oct 2012 09:48:26 -0700 (PDT)
In-Reply-To: <a90637c9-d86c-4309-8aa1-2b72a7453...@r8g2000pbs.googlegroups.com>
References: <a90637c9-d86c-4309-8aa1-2b72a7453...@r8g2000pbs.googlegroups.com>
From: =?UTF-8?Q?Gergely_Juh=C3=A1sz?= <jg.sv...@gmail.com>
Date: Sun, 14 Oct 2012 18:48:26 +0200
Message-ID: <CAKC-o=XfamyB=rcTtMDencD3kJS=p_zhUfxSvCpYAU81gV8...@mail.gmail.com>
Subject: Re: [android-developers] Button#onClickListener thread unsafe?
To: android-developers@googlegroups.com
Content-Type: text/plain; charset=UTF-8

The input events are queued. So your case is valid. When you disable a
button there can be already multiple events in the event queue. Sad
but true :(

On 14 October 2012 10:09, Greenhand <cooperateonl...@gmail.com> wrote:
> In my project, I has a layout as follows:
> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/
> android"
>     android:layout_width="fill_parent"
>     android:layout_height="fill_parent"
>     android:orientation="vertical">
>
>     <Button
>         android:id="@+id/startButton"
>         android:layout_width="fill_parent"
>         android:layout_height="0dp"
>         android:layout_weight="1"
>         android:text="start"
>          />
>     <Button
>         android:id="@+id/stopButton"
>         android:layout_width="fill_parent"
>         android:layout_height="0dp"
>         android:layout_weight="1"
>         android:text="stop"
>          />
> </LinearLayout>
> It is quite simple. There are two buttons. One is start and the other
> is stop.
>
> And an Activity as follows:
> package button.test;
>
> import android.app.Activity;
> import android.os.Bundle;
> import android.util.Log;
> import android.view.View;
> import android.widget.Button;
>
> public class MainActivity extends Activity {
>         private static final String TAG = "MainActivity";
>         private Button startButton;
>         private Button stopButton;
>     @Override
>     public void onCreate(Bundle savedInstanceState) {
>         super.onCreate(savedInstanceState);
>         setContentView(R.layout.activity_main);
>         startButton = (Button)findViewById(R.id.startButton);
>         startButton.setOnClickListener(new View.OnClickListener() {
>
>                         @Override
>                         public void onClick(View arg0) {
>                                 Log.d(TAG,"startButton isEnabled(): "+arg0.isEnabled()+" executing
> on thread "+ Thread.currentThread().getName());
>                                 if(arg0.isEnabled()==false){
>                                         throw new RuntimeException("startButton");
>                                 }
>                                 arg0.setEnabled(false);
>                                 stopButton.setEnabled(true);
>                         }
>                 });
>         stopButton = (Button)findViewById(R.id.stopButton);
>         stopButton.setOnClickListener(new View.OnClickListener() {
>
>                         @Override
>                         public void onClick(View arg0) {
>                                 Log.d(TAG,"stopButton isEnabled(): "+arg0.isEnabled()+" executing
> on thread "+ Thread.currentThread().getName());
>                                 if(arg0.isEnabled()==false){
>                                         throw new RuntimeException("stopButton");
>                                 }
>                                 arg0.setEnabled(false);
>                                 startButton.setEnabled(true);
>                         }
>                 });
>     }
> }
> The logic is: (1)When the start button is clicked, disable it and
> enable the stop button. (2)When the stop button is clicked, disable it
> and enable the start button.
>
> What I expect is that when the onClickListener of a button is
> executing, the button state should be enabled. It is impossible to
> fire the onClickListener when the button is disabled. Therefore, I add
> the if block and the RuntimeException to detect it.
>
> It works when I interact with it but it crashes when I run the monkey
> test (adb shell monkey -p button.test -v 50000).
>
> The logcat messages are as follows:
> D/MainActivity(1836): startButton isEnabled(): true main
> D/MainActivity(1836): stopButton isEnabled(): true main
> D/MainActivity(1836): startButton isEnabled(): true main
> D/MainActivity(1836): startButton isEnabled(): false main
> D/AndroidRuntime(1836): Shutting down VM
> W/dalvikvm(1836): threadid=1: thread exiting with uncaught exception
> (group=0x41745300)
> E/AndroidRuntime(1836): FATAL EXCEPTION: main
> E/AndroidRuntime(1836): java.lang.RuntimeException: startButton
> E/AndroidRuntime(1836):         at button.test.MainActivity
> $1.onClick(MainActivity.java:24)
> E/AndroidRuntime(1836):         at android.view.View.performClick(View.java:
> 4084)
> E/AndroidRuntime(1836):         at android.view.View
> $PerformClick.run(View.java:16966)
> E/AndroidRuntime(1836):         at
> android.os.Handler.handleCallback(Handler.java:615)
> E/AndroidRuntime(1836):         at
> android.os.Handler.dispatchMessage(Handler.java:92)
> E/AndroidRuntime(1836):         at android.os.Looper.loop(Looper.java:137)
> E/AndroidRuntime(1836):         at
> android.app.ActivityThread.main(ActivityThread.java:4745)
> E/AndroidRuntime(1836):         at
> java.lang.reflect.Method.invokeNative(Native Method)
> E/AndroidRuntime(1836):         at
> java.lang.reflect.Method.invoke(Method.java:511)
> E/AndroidRuntime(1836):         at com.android.internal.os.ZygoteInit
> $MethodAndArgsCaller.run(ZygoteInit.java:786)
> E/AndroidRuntime(1836):         at
> com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
> E/AndroidRuntime(1836):         at dalvik.system.NativeStart.main(Native
> Method)
>
> Note that at line 4, the button state is disabled when the
> onClickListener is executing!!! It is quite strange. In addition, both
> the onClickListeners are run on the main thread.
> What I expect is that there is no race condition between the
> onClickListeners because they run on the same thread.
>
> Can anyone explain why the program crashes when I run the monkey
> test?
>
> --
> You received this message because you are subscribed to the Google
> Groups "Android Developers" group.
> To post to this group, send email to android-developers@googlegroups.com
> To unsubscribe from this group, send email to
> android-developers+unsubscribe@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/android-developers?hl=en