使用Volley的Android App获得竞争条件

时间:2015-03-12 14:26:59

标签: android api asynchronous callback android-volley

我正在开发Android移动应用程序,该应用程序本身最重要的功能之一是能够与第三方API服务进行通信。

提供这些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请求也要分离?

我的粗略解决方案是在我完全确定第一个请求完成时,在fireFirstRequest()的回调中调用fireSecondRequest()。 我知道,这是杀死异步请求的绝佳世界的最好方法。

修改后的行动:

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

使用最终查看参数

的fireFirstRequest修改方法
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();
            }
        }
    });
}

1 个答案:

答案 0 :(得分:0)

您没有添加启动Volley RequestQueue的代码部分,但我假设您正在使用以下方式创建默认方式:

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,则可以解决此问题。这样,就不会有2个并发请求和请求将按照发送的顺序发送。

当然,这样做的缺点是,这会大大减慢您的应用。如果所有请求必须等到上一个请求完成,这会在您的应用中造成严重的瓶颈。

也许考虑使用多个请求队列,并且只对依赖此特殊约束的请求使用此特殊请求队列。

希望这有帮助。