Lifecycle是Jetpack提供的一个用于监听生命周期的库。我们知道在使用Activity和Fragment的时候,特别是两者一起使用的时候,生命周期将变得非常的复杂。而且我们需要在Activity和Fragment的生命周期方法里面执行非常多的操作,如地理位置,打开关闭资源等。这会造成很高的耦合。Lifecycle就是为了减低生命周期的耦合而设计的。目的是让各种资源自己监听生命周期变化,在独立的类里面实现相应的生命周期逻辑。
Lifecycle已经包含在androidx里面,也就是下面的包,默认情况下,gradle已经有下面的声明了。

 implementation 'androidx.appcompat:appcompat:1.2.0'

这里有一个特别的地方。就是lifecycle-extensions这个库,只要引用这个库就会把lifecycle里面的所有库都引用进来。

implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'

你也可以手动的引用你需要的库。推荐最开始还是用lifecycle-extensions这个库,避免麻烦。lifecycle-extensions这个库里面的所有API都已经被废弃。

    dependencies {def lifecycle_version = "2.5.0-rc01"def arch_version = "2.1.0"// ViewModelimplementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"// LiveDataimplementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"// Lifecycles only (without ViewModel or LiveData)implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"// Saved state module for ViewModelimplementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"// Annotation processorannotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"// alternately - if using Java8, use the following instead of lifecycle-compilerimplementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"// optional - helpers for implementing LifecycleOwner in a Serviceimplementation "androidx.lifecycle:lifecycle-service:$lifecycle_version"// optional - ProcessLifecycleOwner provides a lifecycle for the whole application processimplementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"// optional - ReactiveStreams support for LiveDataimplementation "androidx.lifecycle:lifecycle-reactivestreams:$lifecycle_version"// optional - Test helpers for LiveDatatestImplementation "androidx.arch.core:core-testing:$arch_version"}

这里推荐使用2.2.0这个版本,因为这个版本提供的ViewModelProvider这个类多出了一个参数的构造方法,具体后面会用到。

1.计算真实运行时间的例子

我们要做这样的一个功能。运行app的时候计算运行时间,app退到后台的时候不计算时间。app继续运行,继续计算运行时间。
我们使用Chronometer这个系统提供的组件来实现这个功能。在onResume的时候开始计时,onPause的时候结束计时。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".lifecycle.LifecycleTimerActivity"><Chronometerandroid:id="@+id/chronometer"android:layout_width="match_parent"android:layout_height="match_parent"android:textSize="20sp"android:gravity="center"/></RelativeLayout>
public class LifecycleTimerActivity extends AppCompatActivity {private Chronometer chronometer;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_lifecycle_timer);chronometer = findViewById(R.id.chronometer);}@Overrideprotected void onResume() {super.onResume();Log.d("LifecycleTimerActivity", "onResume");chronometer.start();}@Overrideprotected void onPause() {super.onPause();chronometer.stop();}
}

上面的代码的运行效果如下,我们在运行到3秒的时候按home键程序退到后台,调用onPause方法。再过来7秒后,我们把app运行到前台。对应的计时也变成了10秒,可见在这种情况下,chronometer即使在后台运行也是会计算时间的。


我们现在有一个需求,就是后台运行时间我们算在“休息时间”里面,不计算入总运行时间。例如,我们在3秒的时候点击home,程序进入后台,过来几秒后,手动让程序回到前台,这时间我们的app还是继续从3秒开始计时。要实现这个功能,只需要把代码改成下面的样子。
elapsedRealtime()这个方法表示系统自开机以来所运行的时间,包括休眠,锁屏。
setBase()实际就是传入一个时间值给mBase变量,这个变量就是个long类型的表示时间的变量。
elapse这个我们自己定义的变量非常关键,用来计算真实运行的时间。在onPause的时候调用。具体逻辑看下面的代码注释。

public class LifecycleTimerActivity extends AppCompatActivity {private Chronometer chronometer;private long elapse;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_lifecycle_timer);chronometer = findViewById(R.id.chronometer);}@Overrideprotected void onResume() {super.onResume();Log.d("LifecycleTimerActivity", "onResume");//getBase获得的时间值就是等于elapsedRealtime的值。//减掉elapse意义是以后每次调用chronometer.getBase()都少了真实运行时间chronometer.setBase(SystemClock.elapsedRealtime() - elapse);chronometer.start();}@Overrideprotected void onPause() {super.onPause();Log.d("LifecycleTimerActivity", "onPause");//计算出真实运行时间elapse = SystemClock.elapsedRealtime() - chronometer.getBase();chronometer.stop();}
}

上面的代码已经完成了我们需要的功能。有没有发现上面代码有什么问题?这仅仅是一个小功能,要是我们有很多代码都写在声明周期里面,生命周期方法将变得非常臃肿。耦合度非常的高。为了解决这个问题,就要使用我们今天的主角Lifecycle了。

2.使用Lifecycle改进

我们可以把前面的逻辑做一个封装,问题的关键是我们怎么感知生命周期。通过实现LifecycleObserver接口就可以感知生命周期了,这个能力是SDK已经帮我们实现了,ComponentActivity已经实现了感知生命周期的功能。所以我们可以直接使用。@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)可以和onResume方法绑定,其它生命周期方法也是一样。

class Timer extends Chronometer implements LifecycleObserver {private long elapse;public Timer(Context context) {super(context);}public Timer(Context context, AttributeSet attrs) {super(context, attrs);}@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)public void startTimer() {setBase(SystemClock.elapsedRealtime() - elapse);start();}@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)public void stopTimer() {elapse = SystemClock.elapsedRealtime() - getBase();stop();}
}

在Activity里面使用封装后的代码:

public class LifecycleTimerActivity extends AppCompatActivity {private Timer chronometer;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_lifecycle_timer);chronometer =  findViewById(R.id.chronometer);}@Overrideprotected void onResume() {super.onResume();Log.d("LifecycleTimerActivity", "onResume");chronometer.startTimer();}@Overrideprotected void onPause() {super.onPause();Log.d("LifecycleTimerActivity", "onPause");//计算出真实运行时间chronometer.stopTimer();}}

通过封装加Lifecycle,代码得到了简化,耦合度也大大减低了。Lifecycle还是非常有用的。

3.结合Service例子

在Service里面我们添加Lifecycle观察者。

public class LocationService extends LifecycleService {public LocationService() {LocationObsever obsever=new LocationObsever(this);getLifecycle().addObserver(obsever);}}

最主要的实现是我们的LocationObsever。

class LocationObsever implements LifecycleObserver {private final Context context;private LocationManager locationManager;private MyLoactionListener myLoactionListener;public LocationObsever(Context context) {this.context = context;}@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)public void startLocation() {Log.d("LocationObsever", "startLocation");locationManager = (LocationManager) context.getSystemService(Service.LOCATION_SERVICE);if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {return;}myLoactionListener = new MyLoactionListener();locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 1,myLoactionListener);}@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)public void stopLocation() {Log.d("LocationObsever", "stopLocation");locationManager.removeUpdates(myLoactionListener);}static class MyLoactionListener implements LocationListener {@Overridepublic void onLocationChanged(Location location) {Log.d("MyLoactionListener", location.toString());}@Overridepublic void onStatusChanged(String provider, int status, Bundle extras) {}@Overridepublic void onProviderEnabled(String provider) {}@Overridepublic void onProviderDisabled(String provider) {}}}
public class LocationActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_location);}public void start(View view) {startService(new Intent(this, LocationService.class));}public void stop(View view) {stopService(new Intent(this,LocationService.class));}
}

最主要的就是LocationManager这个类,可以获取经纬度等信息。可以通过下面的adb代码改变。

adb -s emulator-5554 emu geo fix -122.08400000000002 37.421998333333335
adb -s emulator-5554 emu geo fix -122.08400000000002 38.421998333333335 

4.application配合Lifecycle

Application也是可以被Lifecycle监听的,当然和一般的activity不同,Application的onDestory永远不会被调用。代码也是非常的简单。

public class App extends Application {@Overridepublic void onCreate() {super.onCreate();ProcessLifecycleOwner.get().getLifecycle().addObserver(new ApplicationObsever());}
}
public class ApplicationObsever implements LifecycleObserver {@OnLifecycleEvent(Lifecycle.Event.ON_START)public void onStart() {Log.d("ApplicationObsever", "onStart");}@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)public void onCreate() {Log.d("ApplicationObsever", "onCreate");}@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)public void onResume() {Log.d("ApplicationObsever", "onResume");}@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)public void onPause() {Log.d("ApplicationObsever", "onPause");}@OnLifecycleEvent(Lifecycle.Event.ON_STOP)public void onStop() {Log.d("ApplicationObsever", "onStop");}
}

android Jetpack之Lifecycle的使用相关推荐

  1. Android JetPack系列---Lifecycle

    Android JetPack系列-Lifecycle jetpack也出来很长一段时间了,最近比较闲,然后顺便记录一下自己的学习.然后准备打算的是写一个一系列的文章来完成自己对jetpack 的了解 ...

  2. Android Jetpack之LifeCycle

    目录 Jetpack 1.那么Jetpack是什么呢? 2.为何使用Jetpack? 3. Jetpack与AndroidX LifeCycle 1.LifeCycle的作用​编辑 2. LifeCy ...

  3. Android Jetpack之DataBinding+ViewModel+LiveData+Room

    Android Jetpack之ViewModel.LiveData Android Jetpack之LifeCycle 前言 Jetpack是一个由多个技术库组成的套件,可帮助开发者遵循最佳做法,减 ...

  4. Android Jetpack组件ViewModel基本使用和原理分析

    本文整体流程:首先要知道什么是 ViewModel,然后演示一个例子,来看看 ViewModel 是怎么使用的,接着提出问题为什么是这样的,最后读源码来解释原因! 1.什么是ViewModel 1.1 ...

  5. Android Jetpack 组件之 Lifecycle源码

    1.前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面. A ...

  6. Android Jetpack 组件之 Lifecycle使用

    1.前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面. A ...

  7. Android databingding与jetpack的lifecycle使用与比较

    1.开发环境Android studio 3.4.0,kotlin 2.databinding用法 3.jetpack lifecycles的LiveData 和 ViewModel用法 测试效果如下 ...

  8. Android Jetpack架构组件之 Room(使用、源码篇)

    2019独角兽企业重金招聘Python工程师标准>>> 1.前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发 ...

  9. Android Jetpack组件之Hilt使用

    前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面. And ...

最新文章

  1. 提高你的Java代码质量吧:让我们疑惑的字符串拼接方式的选择
  2. 算法与数据结构题目的 PHP 实现:栈和队列 由两个栈组成的队列
  3. 给自己科普系列:你刚才在淘宝上买了一件东西
  4. 基于几何距离的椭圆拟合
  5. centos系统linux复制命令行,linux系统CentOS7中find命令使用
  6. python怎么发布pycharm_如何使用PyCharm将代码上传到GitHub上(图文详解)
  7. ajax怎么模拟请求,如何模拟AJAX请求?
  8. flume channel monitor实现源码分析
  9. select下拉选择框
  10. 局域网计算机如何传输文件,局域网如何快速传输文件|同一个局域网传输文件的方法...
  11. 卡方拟合优度检验怎么做?
  12. java微信服务通知
  13. 春节感悟 - 原年人的爱和恨
  14. govendor使用笔记
  15. [渝粤教育] 南京师范大学 中国古代文学(一) 参考 资料
  16. msfvenom制作简易后门程序
  17. 微信步数日历打卡小程序
  18. 搜索引擎下拉食云速捷详细_移动端下拉框寻云速捷/-/移动端下拉框跃云速捷-...
  19. Flink Table 和 DataStream 转换
  20. 五种蓝牙耳机,到底谁才是你的菜

热门文章

  1. 记一次,朋友圈9宫格图片分割线效果混账代码的优化
  2. 详解 Chrome 「V8 」引擎,让你更懂JavaScript !
  3. ctfshow-web363(SSTI)
  4. 通过python构建一个区块链来学习区块链
  5. 中南大学计算机学院的辅导员,我院田生伟院长一行访问中南大学计算机学院
  6. 【恭喜考研拟录取】极力推荐科研必备软件,让你科研生涯事半功倍(3万字超全总结-码住系列)
  7. 卑微且强大的Gumbel分布
  8. 进程fork和exec ---Unix网络编程笔记
  9. vue:$emit失效
  10. bdsup2sub java_蓝光原盘压制Remux和Rip、Re 图文实例教程