android.arch.lifecycle提供的类和接口可以让你构建能感知生命周期(lifecycle-aware)的类。所谓可以感知生命周期就是能够根据Activity或者Fragment的生命周期自行调整类的行为。
Android系统中定义的大多数组件都是有生命周期的。这些组件的生命周期是由系统管理的。作为一个开发者必须遵守这些生命周期的规则,否则就会出现内存泄漏或者应用崩溃的情况。
例如:我们需要在Activity中做一个对位置的监听:在Activity生命周期内 处理调用MyLocationListener 的开始与停止方法。
class MyLocationListener {
public MyLocationListener(Context context, Callback callback) { // ... }
void start() { // connect to system location service }
void stop() { // disconnect from system location service } }
class MyActivity extends AppCompatActivity
{
private MyLocationListener myLocationListener;
public void onCreate(...) {
myLocationListener = new MyLocationListener(this, (location) -> { // update UI });
}
public void onStart() { super.onStart(); myLocationListener.start(); }
publicvoid onStop() { super.onStop(); myLocationListener.stop(); } }
功能再扩展一下:如果满足某种条件,才开始监听位置的改变
class MyActivity extends AppCompatActivity {
private MyLocationListener myLocationListener;
public void onCreate(...) { myLocationListener = new MyLocationListener(this,location -> { // update UI }); }
public void onStart() {
super.onStart();
Util.checkUserStatus(
result -> {
// what if this callback is invoked AFTER activity is stopped?
if (result) {myLocationListener.start(); } }); }
public void onStop() { super.onStop(); myLocationListener.stop(); } }
上面的代码存在的问题:
逻辑问题:问题1 myLocationListener
的stop()
方法在start()
之前有可能执行了(Util.checkUserStatus方法比较耗时),这本身在逻辑上就是不合理的。
问题2 myLocationListener
过一段时间开始执行start()
,然后没有stop的代码被调用了。这意味着如果没有其他操作,Activity将会一直在后台监听Location的改变。
如何解决上述的问题,以及更好的优化代码。Android提供了Lifecycle组件
如何解决这两种问题:Lifecycle。 代码如下
public class MyLocationListener implements LifecycleObserver {
private boolean enabled =false;
protected Lifecycle lifecycle ;
public MyLocationListener(Contextcontext, Lifecycle lifecycle) {
this.lifecycle = lifecycle ;
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
void start(){
LogUtils.i("onstart ${enabled}") ;
if (enabled) {
// connect
}
}
public void enable(){
enabled =true;
if (lifecycle.getCurrentState().isAtLeast(STARTED)) {
// connect if not connected
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void stop(){
// disconnect if connected
LogUtils.i("onstart ${stop}") ;
}
}
在Fragment Or AppCompactActivity注册:
lifecycle.addObserver(MyLocationListener(this, this.lifecycle))
· 保持UI Controllers(Activity/Fragment)中代码足够简洁。一定不能包含如何获取数据的代码,要通过ViewModel获取LiveData形式的数据。
· 用数据驱动UI,UI的职责就是根据数据改变显示的内容,并且把用户操作UI的行为传递给ViewModel。
· 把业务逻辑相关的代码放到ViewModel中,把ViewModel看成是UI和App其他部分的功能的桥梁。但ViewModel不能直接获取数据,要通过调用其他类来获取数据(Repository模式)。
· 使用DataBinding来简化View(布局文件)和UI Controllers(Activity/Fragment)之间的代码
· 如果布局本身太过复杂,可以考虑创建一个Presenter类来处理UI相关的改变。虽然这么做会多写很多代码,但是对于保持UI的简介和可测试性是有帮助的。
· 不要在ViewModel中持有任何View/Activity的context。否则会造成内存泄露。