使用使用计时器的Android应用程序切换方向时,如何保持原始计时器处于活动状态?

使用使用计时器的Android应用程序切换方向时,如何保持原始计时器处于活动状态?,android,timer,android-orientation,Android,Timer,Android Orientation,我正在编写一个应用程序,它使用定时器进程在屏幕上显示时间倒数和总时间。这意味着我至少有两个文本视图,一个用于腿时间,一个用于总时间,当秒数经过时,应该显示一个变化的值(向下) “计时器”的设置方式如下: Handler timerHandler = new Handler(); Runnable timerRunnable = new Runnable() { @Override public void run() { // do something

我正在编写一个应用程序,它使用定时器进程在屏幕上显示时间倒数和总时间。这意味着我至少有两个文本视图,一个用于腿时间,一个用于总时间,当秒数经过时,应该显示一个变化的值(向下)

“计时器”的设置方式如下:

    Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {

    @Override
    public void run() {

        // do something here to display

        processTime();    // process what to be done on a sec by sec basis
        timerHandler.postDelayed(this, 1000);
    }
};
屏幕上有一个按钮用于启动进程,这是启动计时器的代码:

    private ImageButton.OnClickListener onClick_btnStartPlan = new View.OnClickListener() {
    @Override
    public void onClick(View v) {

        // this will begin the actual running of the plan.  It kicks off the timer
        // which also kicks off the gps location listener

        if (currentPlan.size() != 0) {
            setActionButtons(getString(R.string.startButtonPushed));  // reset back to just the play if we stopped the plan
            startLocationUpdates();
            timerHandler.postDelayed(timerRunnable, 0);
        }

    }
};
当我第一次启动程序时,我在onCreate事件中执行一个设置侦听器的函数:

    private void setActivityMainListeners() {
    Log.i(eTAG, "setActivityMainListeners function 1");
    txtPace = (TextView) findViewById(R.id.txtAvgPace);

    TextView txt1 = (TextView) findViewById((R.id.txtAvgPace));
    txt1.setText(" ");
    TextView txt2 = (TextView) findViewById((R.id.txtLegTime));
    txt2.setText(" ");
    TextView txt3 = (TextView) findViewById((R.id.txtTotalTime));
    txt3.setText(" ");

    ImageButton btnCreatePlan = (ImageButton) findViewById(R.id.btnManagePlans);
    btnCreatePlan.setOnClickListener(onClick_btnCreatePlans);
    ImageButton btnSelectPlan = (ImageButton) findViewById(R.id.btnOpenPlan);
    btnSelectPlan.setOnClickListener(onClick_btnOpenPlan);
    ImageButton btnStartPlan = (ImageButton) findViewById(R.id.btnStartPlan);
    btnStartPlan.setOnClickListener(onClick_btnStartPlan);
    ImageButton btnPausePlan = (ImageButton) findViewById(R.id.btnPausePlan);
    btnPausePlan.setOnClickListener(onClick_btnPausePlan);
    ImageButton btnStopPlan = (ImageButton) findViewById(R.id.btnStopPlan);
    btnStopPlan.setOnClickListener(onClick_btnStopPlan);

    createLocationRequest();

    if (!openSession) {
        LinearLayout btnActions = (LinearLayout) findViewById((R.id.lyActionButtons));
        btnActions.setVisibility(View.INVISIBLE);
    }

    // ATTENTION: This was auto-generated to implement the App Indexing API.
    // See https://g.co/AppIndexing/AndroidStudio for more information.
    client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();

}
在我添加切换方向的功能之前,所有这些都工作得很好。然而,我决定添加一个景观,当我这样做的时候,我学到了关于需要保存状态的艰难方法。因此,我研究并添加了以下代码:

    @Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    Log.i(eTAG, "onSaveInstanceState");
    outState.putLong(SAVE_TOTAL_TIME,planTime);
    outState.putString(SAVE_LEG_GAIT,legGait);
    outState.putInt(SAVE_LEG_NUMBER,legNumber);
    outState.putLong(SAVE_LEG_TIME,legTime);
    outState.putBoolean(SAVE_OPEN_SESSION,openSession);
    outState.putStringArrayList(SAVE_CURRENT_PLAN,currentPlan);

}

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    Log.i(eTAG, "onRestoreInstanceState");
    planTime = savedInstanceState.getLong(SAVE_TOTAL_TIME);
    legGait = savedInstanceState.getString(SAVE_LEG_GAIT);
    legNumber = savedInstanceState.getInt(SAVE_LEG_NUMBER);
    legTime = savedInstanceState.getLong(SAVE_LEG_TIME);
    openSession = savedInstanceState.getBoolean(SAVE_OPEN_SESSION);
    currentPlan = savedInstanceState.getStringArrayList(SAVE_CURRENT_PLAN);

}
并修改了我的onCreate以了解更改并重置一些值:

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Log.i(eTAG, "onCreate");

    setTitle(R.string.activityMainTitle);
    setContentView(R.layout.activity_track_it_eq_display);

    // First we need to check availability of play services
    if (checkPlayServices()) {
        Log.i(eTAG, "passed check services");
        // Building the GoogleApi client
        // buildGoogleApiClient();
    }
    setUpGoogleApiClientIfNeeded();
    createLocationRequest();


    setActivityMainListeners();  // set the various handers for the display
    soundStuff();          // Load the sounds and sound processing
    client2 = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();

    if (savedInstanceState != null) {

        Log.i(eTAG, "onCreate orientation change");
        planTime = savedInstanceState.getLong(SAVE_TOTAL_TIME);
        legGait = savedInstanceState.getString(SAVE_LEG_GAIT);
        legNumber = savedInstanceState.getInt(SAVE_LEG_NUMBER);
        legTime = savedInstanceState.getLong(SAVE_LEG_TIME);
        openSession = savedInstanceState.getBoolean(SAVE_OPEN_SESSION);
        TextView legText = (TextView) findViewById(R.id.txtLegTime);
        TextView totText = (TextView) findViewById(R.id.txtTotalTime);
        totText.setText(displayTime(planTime));
        legText.setText(String.format("%1s %2s", gaitLetter(legGait), displayTime(legTime)));
        if (openSession) {
            LinearLayout btnActions = (LinearLayout) findViewById((R.id.lyActionButtons));
            btnActions.setVisibility(View.VISIBLE);
            setActionButtons(getString(R.string.startButtonPushed));
        }
    }

}
现在,当我更改屏幕方向时,两次文本视图将显示一个值,但现在该值被冻结,即使我可以看到日志条目计时器仍在运行

我确实读过关于方向的问题,以及如何在恢复或重新创建交换机时保存数据和重新发布。我不明白的是,视图的计时器发生了什么,我知道程序中发生了什么,但屏幕上没有变化

这是向文本视图显示数据的函数

    private void setLegDisplay() {
    Log.i(eTAG, "setLegDisplay");
    Log.i(eTAG, "    planTime:" + planTime);
    Log.i(eTAG, "    legGait:" + legGait);
    Log.i(eTAG, "    legNumber:" + legNumber);
    Log.i(eTAG, "    legTime:" + legTime);
    Log.i(eTAG, "    openSession:" + openSession);
    TextView legText = (TextView) findViewById(R.id.txtLegTime);
    TextView totText = (TextView) findViewById(R.id.txtTotalTime);
    totText.setText(displayTime(planTime));
    legText.setText(String.format("%1s %2s", gaitLetter(legGait), displayTime(legTime)));

}
是否创建了第二个计时器?如果是,如何确保在交换机仍在运行时将原始计时器保留在交换机中


感谢您在此问题上提供的帮助。

您需要删除
ondestory()中以前的可运行回调

@Override
    protected void onDestroy() {
        super.onDestroy();
        timerHandler.removeCallbacks(timerRunnable);
    }

理想情况下,您应该校正运行计时器的服务。让活动与服务通信并获取计时器值。这将使您从维护配置更改状态的麻烦中解脱出来。

现在我采用这种方法。我必须添加一个开关,指示计时器需要重新启动,因为它最初是通过点击按钮启动的。谢谢你的回答。我对服务一无所知,所以我现在没有尝试这种方法。然而,当我开始阅读时,它似乎是更优雅的方法。据我所知,该服务独立于UI活动运行,因此不受方向更改及其销毁/创建操作的影响。我确实需要弄清楚如何实现启动/停止过程,因为应用程序允许用户启动、暂停和停止计时器。如果我让它工作,我会张贴代码在这里为任何其他人寻找一个简单的解决方案。