2017-08-25 100 views
0

我已經寫了一個菜單爲多個按鈕的應用程序。其中兩個按鈕觸發兩種獨立的藍牙方法。問題是,在多次快速按下這些按鈕時,應用程序崩潰,因爲每種方法都試圖管理藍牙連接(而另一個可能會關閉該連接)。我試圖在任何方法運行時檢查變量'true'並檢查它,但它不起作用。我不確定系統是否在不同的線程中同時運行每種方法,或者是否將方法排入隊列。停止方法從執行按鈕按

問題是,在另一個方法執行時,我該如何停止按下按鈕來運行方法?執行完成後我不需要排隊,我只需要將其阻塞即可。

編輯:添加的以下方法之一的代碼,如請求(另一個是相同的,兩個字符串,這是不相關的在此上下文中的除外):

public void lock(View button_lock) { 
     if(ok) 
      return; 
     if (btAdapter == null) { 
      Context context = getApplicationContext(); 
      CharSequence text = "Bluetooth not supported!"; 
      int duration = Toast.LENGTH_SHORT; 
      Toast toast = Toast.makeText(context, text, duration); 
      toast.show(); 
      return; 
     } 
     else if (address == null) { 
      Context context = getApplicationContext(); 
      CharSequence text = "Please pair your phone with SmartLock."; 
      int duration = Toast.LENGTH_SHORT; 
      Toast toast = Toast.makeText(context, text, duration); 
      toast.show(); 
      return; 
     } 
     if (!btAdapter.isEnabled()) { 
      btAdapter.enable(); 
      ok=true; 
     } 
     mHandler.postDelayed(new Runnable() {public void run() { 
      BluetoothDevice device = btAdapter.getRemoteDevice(address); 
      ParcelUuid[] uuids = device.getUuids(); 
      BluetoothSocket mmSocket; 
      try { 
       mmSocket = device.createRfcommSocketToServiceRecord(uuids[0].getUuid()); 
       mmSocket.connect(); 
       OutputStream out = mmSocket.getOutputStream(); 
       InputStream in = mmSocket.getInputStream(); 
       out.write("1".getBytes()); 
       try { 
        Thread.sleep(1000); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
       in.close(); 
       out.close(); 
       mmSocket.close(); 
       in = null; 
       out = null; 
       mmSocket = null; 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     }}, 1000); 
     Context context = getApplicationContext(); 
     CharSequence text = "Bike locked!"; 
     int duration = Toast.LENGTH_SHORT; 
     Toast toast = Toast.makeText(context, text, duration); 
     toast.show(); 
     mHandler.postDelayed(new Runnable() {public void run() { 
      try { 
       Thread.sleep(1000); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      btAdapter.disable(); 
      ok=false; 
     }}, 2000); 
    } 

回答

1

正如你已經嘗試過它與布爾,semaphore可以在這裏做的伎倆。

0

試試這個:

bluetoothMethod(); 
    bluetoothButton.setEnabled(false); 
    new Handler().postDelayed(new Runnable() { 
     @Override 
     public void run() { 
      bluetoothButton.setEnabled(true); 
     } 
    }, duration); 

(在milis持續時間)

+0

這不能解決問題,只會拖延行動,這是一個不好的方法來處理這個問題,請參閱@Patrick Michel回答以獲得更好的處理方法 –

0

不能在onClick()通過禁用按鈕解決的,因爲Android的事件系統的工作方式這個問題。當用戶按下按鈕時,「點擊」事件排隊到事件隊列。如果用戶快速連續兩次按下按鈕(特別是在低端設備上或UI線程繁忙時),則2個「單擊」事件將被插入到隊列中。你無法防止這一點。

你需要做的是記住你已經處理了「點擊」事件並忽略了之後到達的任何事件(直到你想允許用戶再次點擊)。聽起來你已經嘗試過了。請發佈您的代碼,以便我們可以看到什麼是錯的。


看到你的代碼後,我有以下輸入:

如果mHandler已在主(UI)線程創建的,你有問題你必須代碼在這裏是做網絡I/O和睡眠。你絕對不能在主(UI)線程上做到這一點。確保這些東西在後臺線程中運行。爲此,請創建您自己的Thread或確保您的Handler是在後臺線程上創建的(請參閱HandlerThread作爲一個示例)。

在您撥打postDelayed()之前,請將布爾變量running設置爲true。當發佈的Runnable完成時,該標誌應清除爲false。爲了確保這一點,請將整個run()方法包裝在try/catch中,並清除finally塊中的變量。

lock()中,首先檢查布爾變量running是否爲true。如果是這樣,你應該立即返回,這會忽略在你沒有準備好的時候發生的點擊事件。

+0

我已經添加了上述方法之一的代碼。 –

+0

布爾型「ok」應該與您提出的'running'具有相同的用途。 –

+0

然後我不明白這個問題。請解釋什麼是崩潰,你得到什麼異常以及哪些不起作用。 –