LiveData 和 LifecycleObserver 的区别是什么?

8
我已阅读关于生命周期实时数据的Android官方文档。我知道该类实现了LifeCycleObserver,可以自动打开或关闭位置监听器。我也知道LiveData可以自动激活或停用它。我已尝试使用这两种方式实现位置观察者。它能够正常工作,并在位置更新时显示Toast 2次。
我的问题是,这两种方式有什么区别?如果我真的想要实现像DB连接、GPS位置、下载图像、后台服务等功能,我能否只使用LiveData类?因为我只需要实现活动和非活动函数。

LocationLiveData.java

public class LocationLiveData extends LiveData<Location> {
    private LocationManager locationManager;
    private Context context;

    public LocationLiveData(Context context) {
        this.context = context;
        locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    }

    private LocationListener locationListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            setValue(location);
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onProviderDisabled(String provider) {

        }
    };

    @Override
    protected void onActive() {
        super.onActive();
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        locationManager.removeUpdates(locationListener);
    }
}

MyLocationListener.java

public class MyLocationListener implements LifecycleObserver {
    private LocationManager locationManager;
    private Context context;
    private LocationListener locationListener;


    public MyLocationListener(LifecycleActivity lifecycleActivity, LocationListener callback) {
        // ...
        this.context = lifecycleActivity;
        locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        locationListener = callback;

    }

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void onResume() {
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void onPause() {
        locationManager.removeUpdates(locationListener);
    }
}

ComponentActivity.java

public class ComponentActivity extends LifecycleActivity {
    public static final int REQUEST_CODE = 200;
    private MyLocationListener myLocationListener;
    public static class MyLiveData extends ViewModel {
        private LocationLiveData locationLiveData;

        public void init(Context context) {
            locationLiveData = new LocationLiveData(context);
        }

        public LocationLiveData getLocationLiveData() {
            return locationLiveData;
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_component);
//        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
//        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},
                REQUEST_CODE);
        // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
        // app-defined int constant. The callback method gets the
        // result of the request.

        //use the live data observer
        MyLiveData myLiveData = ViewModelProviders.of(this).get(MyLiveData.class);
        myLiveData.init(this);
        myLiveData.getLocationLiveData().observe(this, new Observer<Location>() {
            @Override
            public void onChanged(@Nullable Location s) {
                Toast.makeText(ComponentActivity.this, String.format("Lat : %.2f, Lon : %.2f", s.getLongitude(), s.getLatitude()), Toast.LENGTH_SHORT).show();
            }
        });
        //use the life cycle observer
        getLifecycle().addObserver(new MyLocationListener(this, new LocationListener() {
            @Override
            public void onLocationChanged(Location s) {
                Toast.makeText(ComponentActivity.this, String.format("Lat : %.2f, Lon : %.2f", s.getLongitude(), s.getLatitude()), Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onStatusChanged(String provider, int status, Bundle extras) {

            }

            @Override
            public void onProviderEnabled(String provider) {

            }

            @Override
            public void onProviderDisabled(String provider) {

            }
        }));


    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case 200: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    // permission was granted, yay! Do the
                    // contacts-related task you need to do.

                } else {

                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                }
                return;
            }

            // other 'case' lines to check for other
            // permissions this app might request
        }
    }

}

1
“我能只使用LiveData类吗?” -- 当然可以。LiveData有自己的LifecycleObserver,没有必要实现你自己的。 - CommonsWare
是的,这让我产生了一个问题。如果我需要从实时数据中发送最新的位置信息,为什么我必须使用LifecycleObserver?此外,我不需要使用LifecycleObserver来实现DB连接、HTTP请求,因为LiveData更容易实现。我无法确定在什么特定情况下需要实现LifecycleObserver。 - Long Ranger
1
“如果我需要从实时数据中发送最新的位置信息,为什么我必须使用LifecycleObserver?”--其实不用。 “我无法确定在什么特定情况下需要实现LifecycleObserver”--如果您想要创建某些其他使用模式或集成到其他内容中的LiveData的同级,则可以使用它。例如,RxAndroid可能会利用LifecycleObserver - CommonsWare
我对此有了新的想法。如果LiveData是新应用程序开发的更好模式,那么LifecycleObserver应该被视为旧应用程序迁移到新结构的桥梁。他们需要通过实现LifecycleObserver从onPause()、onDestory()方法中移除GPS、Downloader。正如您所看到的,MyLocationListener和LocationLiveData的结构非常相似。 - Long Ranger
我能否只使用LiveData类?因为我只需要实现活动和非活动函数。我认为这就是区别所在。在LiveData中,您被迫为Activity中的位置数据更改编写观察者(onChange())。即onChange()只能有一个名为Location的参数,您无法从LiveData发送更多信息。它仅限于位置数据,因此命名为“LiveData”。而在LifecycleObserver中,没有这样的强制性规定。您的Lifecycleobserver实现可以自由地以任何方式响应Activity。 - Hanif
3个回答

2

从更高的抽象层面来看,我认为:

  • LiveData 是一个数据持有者,它托管一些数据,与其他不同之处在于它是 LifeCycle 感知型 的。因此,它是一个 可观察的数据持有者,而不是观察者!
  • LifecycleObserver 则是一个关心生命周期的观察者。

我相信这是主要的区别。


但是LiveData在内部使用LifeCycleObserver - Florian Walther

2
它们是两个不同的东西,分别扮演着不同的角色。简而言之,
  • LifeCycle 以有效且易于使用的方式解决了 Android 生命周期问题。它有两个主要部分:LifecycleOwner 公开其状态更改,LifecycleObserver 监听这些更改以采取适当的步骤。
  • 另一方面,LiveData 利用响应式编程帮助我们轻松操作数据。它与 Java 8 中的 StreamRxJava 中的 Observer(或 Flowable)有一些相似之处。但是,LiveData 的优势在于它是专门为 Android 设计的生命周期感知组件。因此,它与 LifeCycle 组件密切配合。

1
生命周期所有者 ----------> 生命周期观察者
在上面的箭头图中,没有涉及任何数据。有一个生命周期所有者,其生命周期被公开,然后有一个生命周期观察者,它将观察任何生命周期所有者状态的更改。
生命周期所有者 ----------> LiveData ------------> 观察者
在上面的箭头图中,LiveData是一个数据持有者,它接收生命周期所有者的上下文,应该照顾其生命周期,并且仅当生命周期所有者处于onStartedonResumed状态时,才向观察者(不是LifecycleObserver,而是数据观察者)发出任何数据更改。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接