从服务器返回响应后结束活动,但等待动画结束

6

我通过Volley向服务器发送请求;发送完成后,增加一个显示请求数量的变量。

VolleyGeneral.getInstance().addToRequestQueue(jsonObj,TAG);
numberOfReq++;

然后当我收到响应时,减少该变量。
@Override
public void onResponse(JSONObject response){
    numberOfReq--;
}

在另一方面,我展示了一张图片,使用淡入动画2秒钟,然后完成活动并转到下一个活动。

但是,在完成活动之前,我希望等待所有服务器响应。所以我将这部分写成:

@Override
public void onAnimationEnd(Animation anim){
    while(numberOfReq == 0){
        numberOfReq = -1;
        startActivity(intent);
        finish();
        break;
    }
}

如果服务器在 2 秒内发送响应,一切正常。

但是如果收到响应超过 2 秒,则活动不会结束。


1
Volley库中没有类似onErroronTimeout或其他回调方法吗? - Timuçin
@Tim 是的,有这个功能。但是为什么?我只写了一部分代码。 - Dr.jacky
因为在2秒后动画已经结束,而且它不会再执行while循环。所以里面的代码不会被执行。 - Punit
你可以使用计时器在动画结束后执行代码... - Punit
5个回答

3
也许我没有理解问题,因为答案似乎非常简单。只需在活动“准备完成”时设置标志,然后在onResponse()中检查此条件即可。
要么onAnimationEnd()要么最后一个onResponse()将首先运行,第二个应该启动第二个活动。例如:
private boolean mReadyToProceed;

@Override
public void onAnimationEnd(Animation anim)
{
    if (numberOfReq == 0)
        startOtherActivityAndFinish();
    else
       mReadyToProceed = true;
}

@Override
public void onResponse(JSONObject response)
{
    numberOfReq--;
    if (mReadyToProceed && numberOfReq == 0)
        startOtherActivityAndFinish();
}

(注意:确保递减和比较不受其他请求线程的影响,可能需要使用锁或使用 AtomicInteger)。

3

你知道Volley创建和维护多个线程的事实吧?

增量/减量操作不是线程安全的。相反,使用类似以下的内容:

AtomicInteger numberOfReq = new AtomicInteger(0);

numberOfReq.incrementAndGet(); // ++

numberOfReq.decrementAndGet(); // --

我不确定这是否是你问题的原因,但即使不是,这也是一个潜在的错误。

编辑:

将numberOfReq设置为volatile int并不能解决问题。

volatile并不能保证原子性。它只能保证下一个读取变量的线程会看到先前线程执行操作后的确切值。

现在,增加(和减少)操作实际上是一个三元组:

a = x;
b = a + 1;
x = b;

如果没有强制使用AtomicInteger等原子操作,这个计算过程中即使使用了volatile修饰变量,其他线程也可能会在计算中间访问该变量,从而影响增量的正确性。

我只是按照这个答案进行操作:https://dev59.com/nXPYa4cB1Zd3GeqPk5rA我不确定,但我认为你是正确的。我不确定是因为我没有在多线程模式下编写应用程序。另一个原因是volatile关键字的使用是什么? - Dr.jacky

0

你应该将启动另一个活动的方法分离出来。像这样:

private boolean animationEnded = false;    

@Override
public void onResponse(JSONObject response){
    numberOfReq--;
    checkStartOtherActivity();
}

@Override
public void onAnimationEnd(Animation anim){
    animationEnded = true;
    checkStartOtherActivity();
}

public void checkStartOtherActivity(){
    if (numberOfReq == 0 && animationEnded){
         startActivity(intent);
         finish();
    }
}

0
为什么不把检查变成双向的,而不是单向的,即:
如果响应在你动画时到达,则你的onAnimationEnd()必须负责关闭并启动新活动
否则,图像动画结束之前的onResponse()必须负责执行活动完成和新活动。
附注:关于线程安全变量,@matiash似乎已经解释得足够清楚了。

0
如matiash所回答的,你可以在onResponse()中设置一个标志,并检查该值以获得所需的结果,或者你可以使用广播接收器,这也是一个有效的解决方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接