嘿,我是编程新手,特别是在java和xml中。我想创建一个游戏,其中进度条显示任务要做的时间,但Android Studio一直在说,我需要声明一个最终变量来使用i ++和mProgressBar.setProgress(i);因为它在一个内在的类。但据我所知,最终变量不能改变它的价值。我应该更改什么才能使代码再次运行?
@Override
public void onResume() {
super.onResume();
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
final ImageView ball = (ImageView) findViewById(R.id.ball);
ball.setOnTouchListener(new View.OnTouchListener()
{
PointF DownPT = new PointF(); // Record Finger Position When Pressed Down
PointF StartPT = new PointF(); // Record Start Position of 'ball'
@Override
public boolean onTouch(View v, MotionEvent event)
{
int eid = event.getAction();
switch (eid)
{
case MotionEvent.ACTION_MOVE :
PointF mv = new PointF( event.getX() - DownPT.x, event.getY() - DownPT.y);
ball.setX((int)(StartPT.x+mv.x));
ball.setY((int)(StartPT.y+mv.y));
StartPT = new PointF(ball.getX(), ball.getY() );
break;
case MotionEvent.ACTION_DOWN :
DownPT.x = event.getX();
DownPT.y = event.getY();
StartPT = new PointF(ball.getX(), ball.getY() );
break;
case MotionEvent.ACTION_UP :
// Nothing have to do
break;
default :
break;
}
return true;
}
});
ProgressBar mProgressBar;
CountDownTimer mCountDownTimer;
int i=0;
mProgressBar=(ProgressBar)findViewById(R.id.progressBartime);
mProgressBar.setProgress(i);
mCountDownTimer=new CountDownTimer(3000,1000) {
@Override
public void onTick(long millisUntilFinished) {
Log.v("Log_tag", "Tick of Progress"+ i+ millisUntilFinished); //i needs to be declared as final
i++; //i needs to be declared as final
mProgressBar.setProgress(i); //mProgressBar needs to be declared as final
}
@Override
public void onFinish() {
//Do what you want
i++; //i needs to be declared as final
mProgressBar.setProgress(i); //mProgressBar needs to be declared as final
}
};
mCountDownTimer.start();
}
}
答案 0 :(得分:2)
因为您正在使用内部类,所以它无法访问自身之外的可变变量。尝试使用AtomicInteger
,因为可以将其设置为final,因此您可以执行以下操作:
// Outer class (where I is currently defined)
final AtomicInteger i = new AtomicInteger();
//Inner class (within the onTick function)
i.incrementAndGet();
然后检索值使用i.get()
对于您的特定情况,您实际上可以在内部类中设置i
变量。
e.g。
CountDownTimer mCountDownTimer;
final ProgressBar mProgressBar=(ProgressBar)findViewById(R.id.progressBartime);
mProgressBar.setProgress(i);
mCountDownTimer=new CountDownTimer(3000,1000) {
int i = 0;
@Override
public void onTick(long millisUntilFinished) {
Log.v("Log_tag", "Tick of Progress"+ i+ millisUntilFinished); //i needs to be declared as final
i++;
mProgressBar.setProgress(i); //mProgressBar needs to be declared as final
}
@Override
public void onFinish() {
//Do what you want
i++;
mProgressBar.setProgress(i); //mProgressBar needs to be declared as final
}
};
由于mProgressBar不需要是可变的,因此您可以将其设置为最终变量而不会出现任何问题。
编辑:更新为什么最终可以使用
mProgressBar
可以设置为final的原因是它是一个对象,最终变量对象的引用不能更改,但是任何未设置的值都是最终的在对象内部可以改变,这就是setProgress
将起作用的原因。但是,对于原始变量,它们只能设置一次,这是为了提高性能。
This有一个很好的解释,为什么你不能修改本地类的非最终局部变量。
本地类可以绝对引用实例变量。他们无法引用非最终局部变量的原因是因为本地类实例可以在方法返回后保留在内存中。当方法返回时,局部变量超出范围,因此需要它们的副本。如果变量不是最终的,那么方法中变量的副本可能会改变,而本地类中的副本则没有,所以它们会不同步。