2016-04-24 54 views
0

從Android活動中,我發送由用戶按下UI上的按鈕驅動的http請求。 我不想同時運行多個請求(OutlookClient崩潰)。通過回調寫入的布爾值上的競爭條件並在活動中讀取

我的問題是:是否有可能有競爭條件由於回調結果編寫相同的布爾值(使用runOnUiTread)在發送新的請求之前讀取?

感謝

// Should this be either "volatile" or atomic ?? 
private boolean isThereAPendingRequest = false; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 

    genericClient = clientInitializer.create(this); 
    // ... 

    isThereAPendingRequest = true; // still have to login 

    Futures.addCallback(genericClient.logon(this, scopes), new FutureCallback<Boolean>() { 
     @Override 
     public void onSuccess(Boolean result) { 

      // ... 
      isThereAPendingRequest = false; 
     } 

     @Override 
     public void onFailure(@NonNull Throwable t) { 

      // ... 
      isThereAPendingRequest = false; 
     } 
    }); 

    // ... 
} 

// ... 

public void getBookings(View view){ 

    if(isThereAPendingRequest){ 
     Toast.makeText(getApplicationContext(), "There's already a pending request. Try in a few seconds.", Toast.LENGTH_LONG).show(); 
     return; 
    } 

    isThereAPendingRequest = true; 

    Futures.addCallback(genericClient.getCalendarEvents(), new FutureCallback<List<List>>(){ 
     @Override 
     public void onSuccess(final List<List> resultCalendars) { 

      Log.d("APP", "Success. Result: "+resultCalendars); 

      runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 

        // .. 

        isThereAPendingRequest = false; 
      } 
     } 
    } 
    // .. 
} 

public void sendBooking(View view){ 

    if(isThereAPendingRequest){ 
     Toast.makeText(getApplicationContext(), "There's already a pending request. Try in a few seconds.", Toast.LENGTH_LONG).show(); 
     return; 
    } 

    isThereAPendingRequest = true; 

    Futures.addCallback(genericClient.sendBooking(booker, title), new FutureCallback<List<String>>(){ 
     @Override 
     public void onSuccess(final List<String> resultBooking) { 

       Log.d("APP", "Success. Result: "+resultBooking); 

       runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 

         // ... 
         isThereAPendingRequest = false; 
        } 
       }); 
     } 
     @Override 
     public void onFailure(Throwable t) { 

      Log.e("APP", "Delete error. Cause: "+t.getLocalizedMessage()); 

      // ... 

      Toast.makeText(getApplicationContext(), "Fail!", Toast.LENGTH_LONG).show(); 

      isThereAPendingRequest = false; 
     } 
    }); 

    }catch(Exception ex){ 
     // logger 
     isThereAPendingRequest = false; 
    } 
} 

UPDATE:這就是所謂的中證期貨的功能之一..

public ListenableFuture<List<List>> getCalendarEvents(){ 

// logger 

final SettableFuture<List<List>> future = SettableFuture.create(); 

DateTime now = new DateTime(DateTimeZone.UTC); 
DateTime workDayEnd = new DateTime(now.getYear(), now.getMonthOfYear(), now.getDayOfMonth(), 23, 59, 0); 

Futures.addCallback(

     mClient .getMe() 
       .getCalendarView() 
       .addParameter("startDateTime", now) 
       .addParameter("endDateTime", workDayEnd) 
       .read(), 
     new FutureCallback<OrcList<Event>>() { 
      @Override 
      public void onSuccess(final OrcList<Event> result) { 

       // ... 

       future.set(myList); 
      } 

      @Override 
      public void onFailure(@NonNull Throwable t) { 
       // ... 
       future.setException(t); 
      } 
     } 
); 

return future; 

}

回答

1

如果getBookingssetBookings是在UI線程上調用兩者都時間,你應該沒問題。您知道在isThereAPendingRequest設置爲false時,請求必須已經完成,因此您可以安全地前往。順便說一下,Futures.addCallback有一個備用簽名,允許您明確地通過Executor,所以如果使用該簽名,則不需要調用runOnUiThread,這會減少一些代碼嵌套。

但是,如果您打算同時調用這些方法,我會看到至少有一個競爭條件需要鎖來防止。如果你有興趣的話,更多細節。


編輯的完整性:

該問題時,你的目標是防止兩個請求來自在同一時間運行。這可能發生兩種情況:

  1. isThereAPendingRequest==false,但實際上有一個掛起的請求。您的代碼迄今爲止是安全的,因爲您只需在請求完成後將其設置爲false即可。這裏你甚至不需要volatile
  2. getBookings和/或setBookings在不同的線程上被調用。如果他們都同時達到if(isThereAPendingRequest)會發生什麼?他們可以同時(並正確)發現它是錯誤的,將其設置爲true,然後獨立發送請求並導致崩潰。

只要您始終在同一個線程上調用這些方法,您就不必擔心(1)和(2)應該成爲問題。

+0

我用一個叫做的函數更新了這個問題。將來我不會收到日曆事件,因爲我會通過BroadcasterReceiver接收這些更新。那樣會導致問題嗎?我應該只是爲了防止問題而將其變得易變?再次感謝 –