最近谷歌安卓团队推出一堆的组件开发架构,方便程序开发者编写更健壮,更安全,更简洁的代码,但是想要熟练地应用它们还是需要学习框架的原理。
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中获取数据。