2015-03-12 2 views
0

Я разрабатываю Android-приложение для мобильных устройств, и одна из самых важных функций самого приложения - это возможность поговорить со сторонней службой API.Android-приложение, использующее волейбол, получает состояние гонки

Служба сторонних разработчиков, предлагающая этот API, хочет, чтобы «маяк» включался в каждый запрошенный мной запрос API.

«Маяк» - это «длинное целое число», и он должен быть уникальным и инкрементным для каждого запроса.

Проблема в следующем: Я уволяю пару этих запросов, и я не знаю, какой из этих запросов будет завершен первым, поэтому я столкнулся с состоянием гонки: где второй запрос заканчивается быстро перед первым запросом аннулирование первого запроса!

Когда кнопка нажата следующее действие будет выполнено:

public void fireRequests(View view) 
{ 
    long first_beacon = System.nanoTime(); 
    fireFirstRequest(view, first_beacon); 

    long second_beacon = System.nanoTime(); 
    fireSecondRequest(view, second_beacon); 
} 

Я использую Volley надлежащим образом, установка обратного вызова и т.д .. пример здесь:

fireFirstRequest метод:

public void fireFirstRequest(View view, long beacon) 
{ 
    final ThirdPartyLib api_lib = new ThirdPartyLib(getActivity()); 

    api_lib.doOperationA(beacon, new ThirdPartyLib.MyOwnCallback() 
    { 
     @Override 
     public void update(JSONObject jsonObject) 
     { 
      try 
      { 
       JSONObject result = jsonObject.getJSONObject("response"); 
       /* my code */ 
       Log.d("doOperationA", result) 
      } 
      catch (JSONException e) 
      { 
       e.printStackTrace(); 
      } 
     } 
    }); 
} 

метод fireSecondRequest:

public void fireSecondRequest(View view, long beacon) 
{ 
    final ThirdPartyLib api_lib = new ThirdPartyLib(getActivity()); 

    api_lib.doOperationB(beacon, new ThirdPartyLib.MyOwnCallback() 
    { 
     @Override 
     public void update(JSONObject jsonObject) 
     { 
      try 
      { 
       JSONObject result = jsonObject.getJSONObject("response"); 
       /* my code */ 
       Log.d("doOperationB", result) 
      } 
      catch (JSONException e) 
      { 
       e.printStackTrace(); 
      } 
     } 
    }); 
} 

Вот журнал выполнения:

03-12 14:26:56.252 18769-18769/it.example.app D/Volley: queued doOperationA 
03-12 14:26:58.124 18769-18769/it.example.app D/Volley: queued doOperationB 
03-12 14:26:59.433 18769-18769/it.example.app D/App: doOperationB: { 
    "error": false, 
    "payload": { 
     "foo": "bar" 
    } 
} 
03-12 14:27:04.181 18769-18769/it.example.app D/App: doOperationA: { 
    "error": true, 
    "errorMessage": "invalid beacon" 
    "payload": {} 
} 

вопрос: что это лучший способ, чтобы следить за маяком перед обжигом запрос API или поддерживать «порядок исполнения» разделение, даже если мы говорим о ASync запрос?

Мое грубое решение - вызвать fireSecondRequest() внутри обратного вызова fireFirstRequest(), когда я полностью уверен, что первый запрос выполнен. Я знаю, это лучший способ убить удивительный мир асинхронных запросов.

модифицирована действие:

public void fireRequests(View view) 
{ 
    long first_beacon = System.nanoTime(); 
    fireFirstRequest(view, first_beacon); 
} 

fireFirstRequest модифицированный метод с окончательного View параметра:

public void fireFirstRequest(final View view, long beacon) 
{ 
    final ThirdPartyLib api_lib = new ThirdPartyLib(getActivity()); 

    api_lib.doOperationA(beacon, new ThirdPartyLib.MyOwnCallback() 
    { 
     @Override 
     public void update(JSONObject jsonObject) 
     { 
      try 
      { 
       JSONObject result = jsonObject.getJSONObject("response"); 
       /* my code */ 
       Log.d("doOperationA", result) 

       /* fire second request */ 
       // EDIT 
       fireSecondRequest(view, System.nanoTime()); 
      } 
      catch (JSONException e) 
      { 
       e.printStackTrace(); 
      } 
     } 
    }); 
} 

ответ

0

Вы не добавить часть кода, который инициирует Volley RequestQueue, но я» m при условии, что вы создаете способ по умолчанию, используя:

RequestQueue requestQueue = Volley.newRequestQueue(context, stack); 

Когда вы делаете это, вы получаете очередь запросов, которая по умолчанию позволяет выполнять 4 параллельных запроса. Вы можете увидеть это, посмотрев на конструктору этот метод используется для создания очереди запросов:

private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 4; 

... 

public RequestQueue(Cache cache, Network network) { 
    this(cache, network, DEFAULT_NETWORK_THREAD_POOL_SIZE); 
} 

Вы можете преодолеть эту проблему, если вместо того, чтобы использовать метод по умолчанию для создания RequestQueue, вы создаете свой собственный RequestQueue с резьбой пул размером 1. Таким образом, не может быть двух одновременных запросов, и запросы будут отправляться в том порядке, в котором они отправлены.

Недостатком этого, конечно же, является то, что это может значительно замедлить ваше приложение.Если все запросы должны ждать завершения предыдущего запроса, это создает серьезное узкое место в вашем приложении.

Возможно, рассмотрите возможность использования более 1 очереди запросов и используйте эту специальную очередь запросов для запросов, которые полагаются на это специальное ограничение.

Надеюсь, это поможет.

+0

Благодарим вас за ответ. Что вы думаете о моем собственном решении? Вызов второго запроса, когда первый завершен? – Matt

+0

это справедливо, но кажется немного громоздким и приведет вас в то, что называется «callback hell», где половина вашего кода вложена в обратные вызовы. С помощью этого метода любой запрос, который полагается на этот маяк, может просто использовать другую очередь запросов, чем остальные запросы вашего приложения, и вы можете просто забыть, что эта проблема существует. –

+0

, я полагаю, что использование другой очереди запросов означает, что запрос, поставленный во вторую очередь, не будет обработан до тех пор, пока все запросы, поставленные в очередь в первую очередь, не будут завершены. это правильно? по вашей точке зрения, что такое завершенный запрос? запрос с его собственным ответом или запрос просто запущен? извините за эти немые вопросы – Matt