文章目錄
- 1、功能分析
- 1.1、秒表功能界面
- 1.2、App結構
- 2、開發視圖布局
- 2.1、activity_main.xml
- 2.2、string.xml
- 3、Activity實作
- 3.1、MainActivity類
- 4、生命周期的應用
- 4.1、問題分析
- 4.2、Activity運行程序
- 4.2、螢屏旋轉,計時不重置
- 4.3、App被切換至后臺,秒表可以暫停
- 5、MainActivity完整代碼
1、功能分析
1.1、秒表功能界面

1.2、App結構
- 1個Activity :MainActivity
- 1個Layout :activity_main.xml
2、開發視圖布局
2.1、activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:id="@+id/time_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="0:00:00"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textSize="80sp"/>
<Button
android:id="@+id/button_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@string/start"
android:onClick="onClickStart"/>
<Button
android:id="@+id/button_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@string/stop"
android:onClick="onClickStop"/>
<Button
android:id="@+id/button_reset"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@string/reset"
android:onClick="onClickReset"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
2.2、string.xml
<resources>
<string name="app_name">Stopwatch</string>
<string name="start">start</string>
<string name="stop"> Stop</string>
<string name="reset">Reset</string>
<string name="time">Time</string>
</resources>
3、Activity實作
3.1、MainActivity類
public class MainActivity extends AppCompatActivity {
//計時的秒數
private int seconds = 0;
//計時的狀態
private boolean running = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//在Activity啟動時,onCreate()方法中啟動runTimer()
runTimer();
}
//啟動計時
public void onClickStart(View view){
running = true;
}
//停止計時
public void onClickStop(View view){
running = false;
}
//重置秒表
public void onClickReset(View view){
running = false;
seconds = 0;
}
//回圈計時方法
private void runTimer(){
final TextView timeView = findViewById(R.id.time_view);
//創建UI執行緒的handler,用于訊息處理
final Handler handler = new Handler();
handler.post(new Runnable() {//立即交一個Runnable,任務在Runnable的run()方法中
@Override
public void run() {
int hours = seconds/3600;
int minutes = (seconds%3600)/60;
int secs = seconds%60;
String time = String.format("%d:%02d:%02d", hours, minutes, secs);
timeView.setText(time);
if(running){
seconds++;
}
//每隔1000ms,重復提交該任務
handler.postDelayed(this,1000);
}
});
}
}
4、生命周期的應用
4.1、問題分析
- 問題一:旋轉螢屏,Android檢測到螢屏方向變化,計時會重置
- 問題二:App被切換至后臺,秒表不能暫停
4.2、Activity運行程序

4.2、螢屏旋轉,計時不重置
-
設備配置變化時,如螢屏旋轉,需保存狀態,重啟時恢復
-
在運行后(running),銷毀(onDestroy())前會呼叫 onSaveInstanceState(),保存狀態到Bundle
-
保存狀態需要覆寫onSaveInstanceState()方法
-
Bundle可存盤鍵值對
bundle.put*(“name”,value)
-
在Bundle中存盤running和seconds
@Override public void onSaveInstanceState(Bundle savedInstanceState){ super.onSaveInstanceState(savedInstanceState); savedInstanceState.putInt("seconds",seconds); savedInstanceState.putBoolean("running",running); }
-
-
在onCreate()方法中恢復,Bundle是其引數,行程第一次新建Activity時為null,
之后為onSaveInstanceState()保存的Bundle-
從Bundle取出鍵值對
bundle.get*(“name”);
-
在Bundle中取出running和seconds
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d("life cycle","onCreate"); setContentView(R.layout.activity_main); if(savedInstanceState!=null){ seconds = savedInstanceState.getInt("seconds"); running = savedInstanceState.getBoolean("running"); } runTimer(); }
-
-
程式運行流程
- 用戶啟動App,點擊start按鈕,開始計時
runTimer()方法開始遞增seconds,并顯示到文本框time_view中 - 旋轉手機,Android檢測到螢屏方向變化,銷毀原Activity前,呼叫onSaveInstanceState()保存實體變數
- Android銷毀Activity,再次新建該Activity再次呼叫onCreate()方法,將保存的Bundle作為引數傳入
- onCreate()方法中,取出Bundle存盤的值并恢復到銷毀前的狀態
- runTimer()方法從旋轉前的seconds繼續計時
- 用戶啟動App,點擊start按鈕,開始計時
4.3、App被切換至后臺,秒表可以暫停
-
解決方法
-
覆寫onStop(),在消失前停止計時
@Override protected void onStop(){ super.onStop(); Log.d("life cycle","onStop"); wasRunning = running; // 記錄之前是否運行, running = false; //將running設定為false以停止計時 } -
覆寫生命周期方法前,必須先呼叫父類的生命周期
super.onStop();
-
覆寫onStart(),在可見前繼續計時
@Override //如果之前running==true,則將running設定為true,繼續計時 protected void onStart(){ super.onStart(); Log.d("life cycle","onStop"); if(wasRunning){ running = true; } } -
App被切換至后臺,Activity物件仍存在,可以使用實體變數存盤狀態
//計時的秒數 private int seconds = 0; //計時的狀態 private boolean running = false; //新的變數,用于在onStop()中保存消失前running的狀態 private boolean wasRunning = false; @Override protected void onStop(){ super.onStop(); Log.d("life cycle","onStop"); //日志并暫停 wasRunning = running; running = false; } @Override protected void onStart(){ super.onStart(); Log.d("life cycle","onStop"); //日志并恢復 if(wasRunning){ running = true; } } -
Activity銷毀前在Bundle保存wasRunning,
Activity重新實體化后從Bundle恢復wasRunning@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d("life cycle","onCreate"); setContentView(R.layout.activity_main); if(savedInstanceState!=null){ seconds = savedInstanceState.getInt("seconds"); running = savedInstanceState.getBoolean("running"); wasRunning = savedInstanceState.getBoolean("wasRunning"); } runTimer(); } @Override public void onSaveInstanceState(Bundle savedInstanceState){ super.onSaveInstanceState(savedInstanceState); savedInstanceState.putInt("seconds",seconds); savedInstanceState.putBoolean("running",running); savedInstanceState.putBoolean("wasRunning",wasRunning); }
-
-
運行流程
- 用戶啟動App,點擊Start按鈕,runTimer()開始遞增seconds并更新文本框
- 用戶點擊Home鍵,Activity消失,Android呼叫onStop()
- 用戶回傳秒表App,Activity可見,Android呼叫onStart()
5、MainActivity完整代碼
public class MainActivity extends AppCompatActivity {
//計時的秒數
private int seconds = 0;
//計時的狀態
private boolean running = false;
//新的變數,用于在onStop()中保存消失前running的狀態
private boolean wasRunning = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("life cycle","onCreate");
setContentView(R.layout.activity_main);
if(savedInstanceState!=null){
seconds = savedInstanceState.getInt("seconds");
running = savedInstanceState.getBoolean("running");
wasRunning = savedInstanceState.getBoolean("wasRunning");
}
//在Activity啟動時,onCreate()方法中啟動runTimer()
runTimer();
}
@Override
protected void onStart(){
super.onStart();
Log.d("life cycle","onStop");
if(wasRunning){
running = true;
}
}
@Override
protected void onStop(){
super.onStop();
Log.d("life cycle","onStop");
wasRunning = running;
running = false;
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState){
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putInt("seconds",seconds);
savedInstanceState.putBoolean("running",running);
savedInstanceState.putBoolean("wasRunning",wasRunning);
}
protected void onDestroy(){
super.onDestroy();
Log.d("life cycle","onDestroy");
}
//啟動計時
public void onClickStart(View view){
running = true;
}
//停止計時
public void onClickStop(View view){
running = false;
}
//重置秒表
public void onClickReset(View view){
running = false;
seconds = 0;
wasTiming = false;
}
//回圈計時方法
private void runTimer(){
final TextView timeView = findViewById(R.id.time_view);
//創建UI執行緒的handler,用于訊息處理
final Handler handler = new Handler();
handler.post(new Runnable() {//立即交一個Runnable,任務在Runnable的run()方法中
@Override
public void run() {
int hours = seconds/3600;
int minutes = (seconds%3600)/60;
int secs = seconds%60;
String time = String.format("%d:%02d:%02d", hours, minutes, secs);
timeView.setText(time);
if(running){
seconds++;
}
//每隔1000ms,重復提交該任務
handler.postDelayed(this,1000);
}
});
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/356133.html
標籤:其他
上一篇:java版仿拼多多Spring Cloud+SpringBoot+mybatis+uniapp b2b2c o2o 多商家入駐商城 直播帶貨商城 電子商務 拼團商城原始碼
