栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Android应用生命周期实现简单的秒表App

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android应用生命周期实现简单的秒表App

文章目录
  • 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



    

        

        
2.2、string.xml

    Stopwatch
    start
     Stop
    Reset
    Time

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继续计时
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);
            }
        });
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/461994.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号