Lifecycle, LifecycleOwner, LifecycleObserver类讲解

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

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中获取数据。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值