上下文
我有一个活动,用户单击击中或错过三圈,然后轮到计算机单击击中或错过。
问题
问题在于,当计算机转动程序时,该程序挂起了回收站视图,并在最终显示结果之前发出多次咔嗒声。您可以在这里看到它:
我尝试过的事情
通过一些故障排除,我发现我应该在后台线程中执行计算机任务,并且所有UI更改都应在runOnUiThread
中执行。所以我有这个(这是onClickEvent):
AsyncTask.execute(new Runnable() {
@Override
public void run() {
playerHit(whosThrowing);
runOnUiThread(new Runnable() {
@Override
public void run() {
setAdapterToDisplayStats(whosThrowing);
tv_numberToHit.setText(numToHit.get(whosThrowing));
if(amountThrownThisRound == 3 && (!opponent.equals("SINGLE"))) {
nextPlayerTurn(whosThrowing);
}
}
});
}
});
break;
case R.id.btn_miss:
AsyncTask.execute(new Runnable() {
@Override
public void run() {
playerMissed(whosThrowing);
runOnUiThread(new Runnable() {
@Override
public void run() {
setAdapterToDisplayStats(whosThrowing);
//Player threw their three darts. Change player.
if(amountThrownThisRound == 3 && (!opponent.equals("SINGLE"))) {
nextPlayerTurn(whosThrowing);
}
}
});
}
});
break;
但是,这不能解决问题,上面的GIF实际上显示了此代码的结果。我首先针对Human v Human场景进行了设计,然后开始实施Human V Computer场景。我认为对于计算机而言,无论点击还是未命中,并在相关按钮上perfomClick()
都可以直接得到结果。
如您在上面的代码块中看到的,大多数方法都在runOnUiThread
中,这是因为这些方法包含至少一部分代码,这些代码可以更改UI,但不会干扰部分内容用户界面。我无法想象我必须遍历每行代码,然后在后台运行还是在UI线程中运行,是吗?就在电脑转弯的时候。
setAdapterToDisplayStats(whosThrowing);
在单独的类中调用onBindViewHolder
,该类将更新recylerview。仅setAdapterToDisplayStats(whosThrowing)
是否可以确保其后的所有内容(即使它在单独的类中)都可以运行?
可能有效的代码
计算机抛出
if(opponent.equals("COMPUTER") && confirmedPlayers.get(0).equals("A.I") && Integer.parseInt(amountThrown.get(0)) % 3 == 0){
btn_hit.setEnabled(false);
btn_miss.setEnabled(false);
for (int i = 0; i < 3; i++) {
takeCompThrow();
}
btn_hit.setEnabled(true);
btn_miss.setEnabled(true);
}
return whosThrowing;
计算机performClick
preformClick是我最初包装在一个可运行块中的内容,认为我调用的任何内容都将在后台线程中完成。虽然这是我第一次遇到问题并将其移至onClick()的地方,但在我阅读UI时,它应该单独完成,但仍然没有乐趣。
private void takeCompThrow() {
boolean hitOrMiss = computerThrow.computerHitOrMiss(compLevel);
if(hitOrMiss) {
btn_hit.performClick();
} else {
btn_miss.performClick();
在重要的情况下,它是如何形成Human V Human的方式:
主要问题
我要去哪里错了?
答案 0 :(得分:1)
我认为问题与该代码块有关,因为您试图在一个非常短的时间内多次更新recyclerview。
for (int i = 0; i < 3; i++) {
takeCompThrow();
}
由于您是计算逻辑的所有者,因此可以直接玩转牌并直接更新结果,而无需点击。在这方面,除非有巨大的计算成本,否则无需使用任何异步任务。 我的第一个建议是,您可以执行以下操作:
if this is computer turn
for 1..3
calculate result for the computer turn
update recyclerview
还有第二种选择,但是我肯定会选择上面的方法。即使这将是一个快速的解决方案,但却不是最好的。您只需要在计算机单击之间设置延迟,即可让Recyclerview计算和重绘元素。因此,它将与现有代码类似:
for (int i = 0; i < 3; i++) {
takeCompThrow();
someDelay();
}