使用使用计时器的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活动运行,因此不受方向更改及其销毁/创建操作的影响。我确实需要弄清楚如何实现启动/停止过程,因为应用程序允许用户启动、暂停和停止计时器。如果我让它工作,我会张贴代码在这里为任何其他人寻找一个简单的解决方案。