更改活动时,计时器对象会翻倍并返回

时间:2016-10-10 16:50:05

标签: android android-layout android-activity

所以我试图制作一款关于金钱的点击游戏。每次单击中间按钮,它会给你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);

3 个答案:

答案 0 :(得分:0)

您必须检查用于启动计时器活动 生命周期方法。我认为您正在使用 onResume 这个问题,并通过返回活动启动另一个计时器。

您可以查看此图表并选择最佳位置,甚至将计时器与活动生命周期分开:

Activity Life-Cycle Diagram

您也可以实现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。当按下launchModeActivity按钮时,此Back会创建一个新Up,因为第二个Activity正在创建Intent以启动该Activity launchMode

尝试将Activity的{​​{1}}设置为Timerandroid: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;
        }
    }

}