所以我试图制作一款关于金钱的点击游戏。每次单击中间按钮,它会给你1欧元,但它也会给出1欧元/秒。 当我去商店活动然后回到MainActivity时遇到问题,它计算为2个计时器正在运行,如果我再次交替活动,那就好像3个计时器同时运行一样。那是因为我宣布了#34; money_per_sec" int,并且不想要2€/ s或更多只是因为我点击" Shop"。 有什么帮助吗?
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
money = loadGame.getInt("money", 0);
money_per_sec = loadGame.getInt("money_per_sec", 0);
money_per_click = loadGame.getInt("money_per_click", 0);
money = money + money_per_sec;
SharedPreferences saveGame = getSharedPreferences(SAVE, 0);
SharedPreferences.Editor editor = saveGame.edit();
editor.putInt("money", money);
editor.putInt("money_per_sec", money_per_sec);
editor.apply();
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_money_per_sec.setText(String.valueOf(money_per_sec));
tv_money_per_click.setText(String.valueOf(money_per_click));
toolbar_title.setText(String.valueOf(money));
}
});
}
}, 1000, 1000);
答案 0 :(得分:0)
您必须检查用于启动计时器的活动 生命周期方法。我认为您正在使用 onResume 这个问题,并通过返回活动启动另一个计时器。
您可以查看此图表并选择最佳位置,甚至将计时器与活动生命周期分开:
您也可以实现Application类并将计时器放在那里。这个类在你的应用程序生命周期中实例化一次:
public class MyApplication extends Application{
private OnTimerTick listener;
public void setListener(OnTimerTick listener) {
this.listener = listener;
}
@Override
public void onCreate() {
super.onCreate();
// start your timer
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
money = loadGame.getInt("money", 0);
money_per_sec = loadGame.getInt("money_per_sec", 0);
money_per_click = loadGame.getInt("money_per_click", 0);
money = money + money_per_sec;
SharedPreferences saveGame = getSharedPreferences(SAVE, 0);
SharedPreferences.Editor editor = saveGame.edit();
editor.putInt("money", money);
editor.putInt("money_per_sec", money_per_sec);
editor.apply();
if(listener!=null)
listener.onTick(money,money_per_sec);
}
}, 1000, 1000);
}
interface OnTimerTick {
void onTick(int money, int moneyPerSec);
}
}
你必须像这样将它添加到你的清单中:
<application
android:name=".MyApplication"
...
您也可以在应用程序的每个位置访问此单例类:
MyApplication application = (MyApplication) getApplication();
在您的MainActivity中:
public class MainActivity extends AppCompatActivity implements MyApplication.OnTimerTick {
private MyApplication application;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
application = (MyApplication) getApplication();
// other stuff
}
@Override
protected void onResume() {
super.onResume();
application.setListener(this);
}
@Override
protected void onPause() {
super.onPause();
application.setListener(null);
}
@Override
public void onTick(final int money, final int moneyPerSec) {
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_money_per_sec.setText(String.valueOf(moneyPerSec));
tv_money_per_click.setText(String.valueOf(moneyPerSec));
toolbar_title.setText(String.valueOf(money));
}
});
}
这就是您可以在任何其他活动中访问计时器的方式。
答案 1 :(得分:0)
首先,您应该考虑使用a Handler
instead of a Timer
。这样,您就可以在Timer
的生命周期内更轻松地管理Activity
。
private final int interval = 1000; // 1 Second
private Handler handler = new Handler();
private Runnable runnable = new Runnable(){
public void run() {
Toast.makeText(MyActivity.this, "C'Mom no hands!", Toast.LENGTH_SHORT).show();
}
};
...
handler.postAtTime(runnable, System.currentTimeMillis()+interval);
handler.postDelayed(runnable, interval);
接下来,根据您的评论:
我实际上在所有其他活动中使用onCreate,但有趣的部分 是,当我改变活动时,计时器仍然运行。当我走的时候 回到具有Timer的活动,它“创建”另一个计时器。
您的Activity
似乎正在使用标准launchMode
。当按下launchMode
或Activity
按钮时,此Back
会创建一个新Up
,因为第二个Activity
正在创建Intent
以启动该Activity
launchMode
。
尝试将Activity
的{{1}}设置为Timer
至android:launchMode="singleTop"
。这会将Intent
从第二个Activity
路由到现有的父Activity
,并触发对onNewIntent
的调用。这样可以防止Activity
重新启动,并创建另一个Timer
。
您还应该终止Timer
onDestroy
方法中的Activity
,否则它将继续运行并可能导致内存泄漏。
答案 2 :(得分:0)
使您的计时器成为活动的实例,而不是匿名类。检查它是否已在onResume()
中运行。如果没有,请启动它。在onDestroy()
中停止。像这样:
class MyActivity extends Activity {
private Timer mTimer;
@Override
public void onResume() {
super.onResume();
if (mTimer == null) {
mTimer = new Timer() {
};
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (mTimer != null) {
mTimer.cancel();
mTimer = null;
}
}
}