最近谷歌安卓团队推出一堆的组件开发架构,方便程序开发者编写更健壮,更安全,更简洁的代码,但是想要熟练地应用它们还是需要学习框架的原理。
Lifecycles的目的就是安卓组件(activities, fragments)在发生状态变化(onStart, onResume)的时候,其它的部分能够相应组件的变化。一个很常见的例子就是位置传感器要把位置实时传递到UI界面上,那么需要在activities onCreate()的状态的时候创建位置传感器,在onStart()的时候开启位置传感器,在onStop的时候停止位置传感器。
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; @Override public void onCreate(...) { myLocationListener = new MyLocationListener(this, (location) -> { // update UI }); } @Override public void onStart() { super.onStart(); myLocationListener.start(); // manage other components that need to respond // to the activity lifecycle } @Override public void onStop() { super.onStop(); myLocationListener.stop(); // manage other components that need to respond // to the activity lifecycle } }代码看上去没有什么问题,但是在真实的例子中,很有很多的监听需要根据状态去更新UI界面,而且有时候onStop可能出现出现在onStart完成之前,导致有些监听的不正确执行。
所以想出来Lifecycle这个框架,它会保存组件的状态信息,允许其它的对象观察这些状态。要理解这个Lifecycle框架,最好知道观察者模式是怎么回事,可以在网上找相关的例子进行查看。
比如有两个人需要知道天气预报的情况,这两个人可以用Observer表示,监听的的天气预报就是State, Owner就是管理这些State变化的。那么在activity中,owener是activity实体,state就是activity的状态,observer就是想要知道变化的对象。
从上图可以看到有五种状态,INITIALIZED, DESTROYED, CREATED, STARTED, RESUME,对象owner只需要被owner加入到观察对象就能感知这些变化,具体原理查看观察者模型。
因此,三者Owner, State, Observer只需要一一对应就可。
public class MyActivity extends Activity implements LifecycleOwner { private LifecycleRegistry mLifecycleRegistry; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mLifecycleRegistry = new LifecycleRegistry(this); mLifecycleRegistry.markState(Lifecycle.State.CREATED); } @Override public void onStart() { super.onStart(); mLifecycleRegistry.markState(Lifecycle.State.STARTED); } @NonNull @Override public Lifecycle getLifecycle() { return mLifecycleRegistry; } }Owner通过LifecycleRegistry进行注册,就可以发送状态发生变化的广播。Android中如果继承AppCompatActivity就可以获得相应的Lifecycle,所以两种方式随意选择。
package com.android.guide.archcomponents; import android.Manifest; import android.content.pm.PackageManager; import android.location.Location; import android.location.LocationListener; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.widget.TextView; import android.widget.Toast; import com.android.guide.R; /** * By using lifecycle-aware components, * you can move the code of dependent components out of the lifecycle * methods and into the components themselves. * * The android.arch.lifecycle package provides classes and interfaces that let * you build lifecycle-aware components—which are components that can automatically adjust * their behavior based on the current lifecycle state of an activity or fragment. */ public class LifecycleEvent extends AppCompatActivity { private static final int REQUEST_LOCATION_PERMISSION_CODE = 1; private LocationListener mGpsListener = new MyLocationListener(); @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.textview); if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_LOCATION_PERMISSION_CODE); } else { bindLocationListener(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) { bindLocationListener(); } else { Toast.makeText(this, "This sample requires Location access", Toast.LENGTH_LONG).show(); } } private void bindLocationListener() { BoundLocationManager.bindLocationListenerIn(this, mGpsListener, getApplicationContext()); } private class MyLocationListener implements LocationListener { @Override public void onLocationChanged(Location location) { TextView textView = findViewById(R.id.text_view); textView.setText(location.getLatitude() + ", " + location.getLongitude()); } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } @Override public void onProviderEnabled(String provider) { Toast.makeText(LifecycleEvent.this, "Provider enabled: " + provider, Toast.LENGTH_SHORT).show(); } @Override public void onProviderDisabled(String provider) { Toast.makeText(LifecycleEvent.this, "Provider disabled: " + provider, Toast.LENGTH_SHORT).show(); } } }编写一个LocationManager的实现,将它传递到Observer中,如果Observer监听到状态的变化,就会更新相关的UI,所以重新编写BoundLocationManager类。
package com.android.guide.archcomponents; import android.annotation.SuppressLint; import android.arch.lifecycle.Lifecycle; import android.arch.lifecycle.LifecycleObserver; import android.arch.lifecycle.LifecycleOwner; import android.arch.lifecycle.OnLifecycleEvent; import android.content.Context; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; public class BoundLocationManager { public static void bindLocationListenerIn(LifecycleOwner lifecycleOwner, LocationListener listener, Context context) { new BoundLocationListener(lifecycleOwner, listener, context); } static class BoundLocationListener implements LifecycleObserver { private final Context mContext; private LocationManager mLocationManager; private final LocationListener mListener; public BoundLocationListener(LifecycleOwner lifecycleOwner, LocationListener listener, Context context) { mContext = context; mListener = listener; // 把这个类加进去监听相关状态的变化,同时把结果返回给传递进来的监听器。 lifecycleOwner.getLifecycle().addObserver(this); } @SuppressLint("MissingPermission") @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) void addLocationListener() { mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, mListener); // Force an update with the last location, if available. Location lastLocation = mLocationManager.getLastKnownLocation( LocationManager.GPS_PROVIDER); if (lastLocation != null) { mListener.onLocationChanged(lastLocation); } } @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) void removeLocationListener() { if (mLocationManager == null) { return; } mLocationManager.removeUpdates(mListener); mLocationManager = null; } } }可以看到直接将mGpsListener的值传递到LocationManager中获取数据。