Android Jetpack 之 Lifecycle – 1

这是我参与更文挑战的第16天,活动详情查看: 更文挑战

Lifecycle 概述

Google官方向我们推出了 Android Architecture Components,其中谈到Android组件处理生命周期的问题,向我们介绍了 Handling Lifecycles。同时,如何利用 android.arch.lifecycle 包提供的类来控制数据、监听器等的 lifecycle。同时,LiveDataViewModel 的 lifecycle 也依赖于Lifecycle框架。不久前, Android Architecture Components 正式Release,Lifecycle也正式植入进了SupportActivity(AppCompatActivity的基类)Fragment中。

简介

Lifecycle 是一个存储某组件(如 acitivity 或 fragment)生命周期状态的信息的类,并且它还允许其他对象观察这个状态。从而在外部实现监听,能够使我们及时根据组件的生命周期变化做出相应动作,比如释放资源等,从而避免内存泄露和程序崩溃。

在开发应用时,我们可能会基于一系列的生命周期实现某种功能。之前一种常见的模式是在 acitivity 和 fragment 的生命周期方法中实现相关组件(dependent components)的行为,然而这种模式会导致混乱的代码和激增的错误。见下面的demo。

class MyPresenter{
    public MyPresenter() {
    }

    void create() {
        //do something
    }

    void start() {
        //do something
    }
    
    void destroy() {
        //do something
    }
}

class MyActivity extends AppCompatActivity {
    private MyPresenter presenter;

    @Override
    public void onCreate(...) {
        presenter= new MyPresenter ();
        presenter.create();
    }
    
	@Override
    public void onStart() {
        super.onStart();
        presenter.start();
    }
    
    @Override
    public void onDestroy() {
        super.onDestroy();
        presenter.destory();
    }
}
复制代码

尽管这个例子看起来没什么问题,但在一个真实的应用中,您会发现最后有太多更新 UI 和其他组件相应当前生命周期状态的调用了。为了管理多个组件,您不得不向 onStart()onStop() 等生命周期方法中添加大量的代码,这样就很难维护。

更糟的是,没人能保证这些组件会在 activity 或 fragment 停止前开始,尤其是在需要执行耗时较长的操作时,例如 onStart() 中的某些配置检查。这就会出现竞争情况(race condition),导致 onStop() 方法提前于 onStart() 结束,从而使这些组件存活得过久。

class MyActivity extends AppCompatActivity {
    private MyPresenter presenter;

    @Override
    public void onCreate(...) {
        presenter= new MyPresenter ();
        presenter.create();
    }
    
	@Override
    public void onStart() {
        super.onStart();
        Util.checkUserStatus(result -> {
            // what if this callback is invoked AFTER activity is stopped?
            if (result) {
                presenter.start();
            }
        });
    }
    
    @Override
    public void onDestroy() {
        super.onDestroy();
        presenter.destory();
    }
}
复制代码

为了复用,也为了不让应用组件变得很臃肿,实现该功能时会选择与生命周期组件解藕,独立成一种组件。这样能够很方便地在应用组件中使用,比如:ActivityFragmentService

Android 官方把它叫做 lifecycle-aware 组件,这类组件会根据其他组件(例如 activity 和 fragment)的生命周期的状态改变而做出反应,从而帮助您编写更有条理、轻量且易于维护的代码。

通过使用能感知生命周期的组件,您就能将相关组件的代码从生命周期方法中移出到这些组件自身中去。

为了方便开发者创建 lifecycle-aware 组件,android.arch.lifecycle 包提供了让您构建能感知生命周期的组件的类和接口。

注意:欲将 android.arch.lifecycle 导入到您的 Android 项目中,请参阅为您的项目添加 Android 架构组件

Android 框架中定义的大部分应用组件都附有相应的生命周期,而生命周期则是由操作系统、或是您的进程中运行的框架代码来管理。它们对于 Android 的正常工作来说是至关重要的,因此您的应用必须尊重其规律,否则就可能导致内存泄漏、甚至应用崩溃。

Demo

  • Prestener继承LifecycleObserver接口

    public interface IPresenter implements LifecycleObserver {
    
        @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
        void onCreate(@NotNull LifecycleOwner owner);
    
        @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
        void onDestroy(@NotNull LifecycleOwner owner);
    
        @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
        void onLifecycleChanged(@NotNull LifecycleOwner owner,
                                @NotNull Lifecycle.Event event);
    }
    
    public class BasePresenter implements IPresenter {
    
        private static final String TAG = "BasePresenter";    
    
        @Override
        public void onLifecycleChanged(@NotNull LifecycleOwner owner, 
                                       @NotNull Lifecycle.Event event) {
    
        }
    
        @Override
        public void onCreate(@NotNull LifecycleOwner owner) {
            Log.d(TAG, "BasePresenter.onCreate" + this.getClass().toString());
        }
    
        @Override
        public void onDestroy(@NotNull LifecycleOwner owner) {
            Log.d(TAG, "BasePresenter.onDestroy" + this.getClass().toString());
        }
    }
    
    public class MainPresenter extends BasePresenter {
        //...
    }
    
    复制代码

    这里我直接将我想要观察到Presenter的生命周期事件都列了出来,然后封装到BasePresenter中,这样每一个BasePresenter 的子类都能感知到Activity容器对应的生命周期事件,并在子类重写的方法中,对应相应行为。

  • 在Activity/Fragment中添加Observer

    public class MainActivity extends AppCompatActivity {
        private IPresenter mObserver;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.d("tag", "onCreate" + this.getClass().toString());
            setContentView(R.layout.activity_main);
            mObserver = new MainPresenter(this);
            getLifecycle().addObserver(mObserver);//添加LifecycleObserver
        }
    
        @Override
        protected void onDestroy() {
            Log.d("tag", "onDestroy" + this.getClass().toString());
            super.onDestroy();
        }
    }
    复制代码

    如此,每当Activity发生了对应生命周期改变,Presenter就会执行对应事件注解的方法,只要通过注解进行声明,就能够使LifecycleObserver观察到对应的生命周期事件。

源码分析

借鉴Android 架构组件(一)——Lifecycle里的一张图进行简单的概括:

image.png

我们先将重要的这些类挑选出来:

  • LifecycleObserver接口(生命周期观察者):实现该接口的类,通过注解的方式,可以通过被LifecycleOwner类的addObserver(LifecycleObserver o)方法注册,被注册后,LifecycleObserver便可以观察到LifecycleOwner生命周期事件
  • LifecycleOwner接口(生命周期所有者):实现该接口的类持有生命周期(Lifecycle对象),该接口的生命周期(Lifecycle对象)的改变会被其注册的观察者LifecycleObserver观察到并触发其对应的事件。
  • Lifecycle(生命周期):和LifecycleOwner不同的是,LifecycleOwner本身持有Lifecycle对象,LifecycleOwner通过其getLifecycle()获取内部Lifecycle对象。
  • State(当前生命周期所处状态):如图所示。
  • Event(当前生命周期改变对应的事件):如图所示,当Lifecycle发生改变,如进入onCreate,会自动发出ON_CREATE事件。

简单来说,LifecycleOwner 用于提供 LifecycleLifecycleObserver 监听 Lifecycle 的状态变化,Lifecycle 则是 ActivityFragment 生命周期状态的抽象。

了解了这些类和接口的职责,接下来原理分析就简单很多了,我们来看下实际Fragment/Activity等类和上述类或接口的联系:

生命周期所有者(LifecycleOwner)

public interface LifecycleOwner {    
    /**     
    * Returns the Lifecycle of the provider.     
    *     
    * @return The lifecycle of the provider.     
    */    
    @NonNull    
    Lifecycle getLifecycle();
}
复制代码

LifecycleOwner 是仅包含了一个方法(getLifecycle())的接口,通过@NonNull强制我们返回Lifecycle对象。

LifecycleOwner用以表示某个类拥有 Lifecycle。这唯一的 getLifecycle() 方法必须由那个类实现。另一方面,如果您试图管理的是整个应用进程的生命周期,请参阅 ProcessLifecycleOwner

该接口将 Lifecycle 的所有权从各自的类(如 FragmentAppCompatActivity)中抽象出来,并允许用户编写与其协作的组件。任何定制的应用类都可以实现该接口。

实现了 LifecycleObserver 的接口的组件能够和实现了 LifecycleOwner 的组件无缝衔接,因为后者可以提供一个被前者注册以观察的生命周期。

如果一个库提供了需要和 Android 生命周期协调的类,我们推荐您使用能感知生命周期的组件。您的库的用户可以轻易地整合这些组件,而毋须手动地管理生命周期。

26.1.0 及更新版本的支持库里的 Fragments 和 Activity 已经实现了 LifecycleOwner 接口。

androidx.fragment.app.Fragment

我们先看看androidx中的fragment中的实现

public class Fragment implements ..., LifecycleOwner {
     
    LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
    
    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
    
    void performCreate(Bundle savedInstanceState) {
        //1.先执行生命周期方法
        onCreate(savedInstanceState);
        //...省略代码
        //2.生命周期事件分发  
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
    }
    
    void performStart() {
        onStart();
        //...
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
    }
    
    void performResume() {
        onResume();
        //...
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
    }
    
    void performPause() {
        //3.注意,调用顺序变了
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
        //...
        onPause();
    }
    
     void performStop() {
       mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
        //...
        onStop();
    }

    void performDestroy() {
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
        //...
        onDestroy();
    }    
}
复制代码

随着Fragment不同走到不同的生命周期,除了暴露给我们的生命周期方法onCreate/onStart/…./onDestroy等,同时,Fragment内部的Lifecycle对象(就是mLifecycleRegistry)还将生命周期对应的事件作为参数传给了 LifecycleRegistry#handleLifecycleEvent() 方法。这个方法分析见后文。

同时,你会发现Fragment中performCreate()、performStart()、performResume()会先调用自身的onXXX()方法,然后再调用LifecycleRegistry的handleLifecycleEvent()方法;而在performPause()、performStop()、performDestroy()中会先LifecycleRegistry的handleLifecycleEvent()方法 ,然后调用自身的onXXX()方法。

参照Android 架构组件(一)——Lifecycle文中的时序图:

image.png

androidx.core.app.ComponentActivity

我们再看看androidx中的ComponentActivity中的实现

public class ComponentActivity extends Activity implements LifecycleOwner,ViewModelStoreOwner, SavedStateRegistryOwner, OnBackPressedDispatcherOwner{
    private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //...
        ReportFragment.injectIfNeededIn(this);
        //...
    }
    
    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
}
复制代码

上面就是lifecycle相关的核心代码了,可以看到它并没有像Fragment一样在各个生命周期函数中调用mLifecycleRegistry.handleLifecycleEvent来发出事件,那么它是如何让做LifecycleObserver感受到到ComponentActivity的生命周期变化的呢?

其实关键点就在于onCreate()方法中的ReportFragment.injectIfNeededIn(this)

我们看下ReportFragment

public class ReportFragment extends Fragment {
    private static final String REPORT_FRAGMENT_TAG = "androidx.lifecycle"
            + ".LifecycleDispatcher.report_fragment_tag";

    public static void injectIfNeededIn(Activity activity) {
        // ProcessLifecycleOwner should always correctly work and some activities may not extend
        // FragmentActivity from support lib, so we use framework fragments for activities
        android.app.FragmentManager manager = activity.getFragmentManager();
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
            // Hopefully, we are the first to make a transaction.
            manager.executePendingTransactions();
        }
    }

    static ReportFragment get(Activity activity) {
        return (ReportFragment) activity.getFragmentManager().findFragmentByTag(
                REPORT_FRAGMENT_TAG);
    }

    private ActivityInitializationListener mProcessListener;

    private void dispatchCreate(ActivityInitializationListener listener) {
        if (listener != null) {
            listener.onCreate();
        }
    }

    private void dispatchStart(ActivityInitializationListener listener) {
        if (listener != null) {
            listener.onStart();
        }
    }

    private void dispatchResume(ActivityInitializationListener listener) {
        if (listener != null) {
            listener.onResume();
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        dispatchCreate(mProcessListener);
        dispatch(Lifecycle.Event.ON_CREATE);
    }

    @Override
    public void onStart() {
        super.onStart();
        dispatchStart(mProcessListener);
        dispatch(Lifecycle.Event.ON_START);
    }

    @Override
    public void onResume() {
        super.onResume();
        dispatchResume(mProcessListener);
        dispatch(Lifecycle.Event.ON_RESUME);
    }

    @Override
    public void onPause() {
        super.onPause();
        dispatch(Lifecycle.Event.ON_PAUSE);
    }

    @Override
    public void onStop() {
        super.onStop();
        dispatch(Lifecycle.Event.ON_STOP);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        dispatch(Lifecycle.Event.ON_DESTROY);
        // just want to be sure that we won't leak reference to an activity
        mProcessListener = null;
    }

    private void dispatch(Lifecycle.Event event) {
        Activity activity = getActivity();
        if (activity instanceof LifecycleRegistryOwner) {
            ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
            return;
        }

        if (activity instanceof LifecycleOwner) {
            Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
            if (lifecycle instanceof LifecycleRegistry) {
                ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
            }
        }
    }

    void setProcessListener(ActivityInitializationListener processListener) {
        mProcessListener = processListener;
    }

    interface ActivityInitializationListener {
        void onCreate();

        void onStart();

        void onResume();
    }
}
复制代码

ReportFragment代码很简单,重写生命周期函数,并调用dispatch(Lifecycle.Event event)方法,来分发生命周期事件,这就是“生命周期感知能力”的来源。向 Activity 注册一个无 UI 的 Fragment 也叫 Headless Fragment 用于将各种 Activity 回调分离出来是个常用的做法,比如权限请求库 RxPermission ,以及 airbnb 开源的用于URL跳转的 DeepLinkDispatch(前者是使用空的 Fragment,后者使用的是空的 Activity)

Activity 的生命周期变化是如何传递到 LifecycleObserver 有了清晰的图表:

最终也是调用((LifecycleRegistry) lifecycle).handleLifecycleEvent(event)方法,和上面一样,先不分析,下文会有分析的。

android.app.Activity

这是普通Activity,如果想让这个Activity定制成 LifecycleOwner,您可以使用 LifecycleRegistry

网上很多文章都是按下面的方法做的

public class MyActivity extends Activity implements LifecycleOwner {
    private LifecycleRegistry lifecycleRegistry;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        lifecycleRegistry = new LifecycleRegistry(this);
        lifecycleRegistry.markState(Lifecycle.State.CREATED);
    }

    @Override
    public void onStart() {
        super.onStart();
        lifecycleRegistry.markState(Lifecycle.State.STARTED);
    }

    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return lifecycleRegistry;
    }
}
复制代码

思路就是实例化一个LifecycleRegistry,然后重写Activity生命周期函数,再通过lifecycleRegistry.markState来分发事件。

虽然通过重写 Activity 生命周期,并通过在各方法中仅添加一行lifecycleRegistry.markState()代码就能实现生命周期的感知。但是,作为推动社会发展的“懒人” — 程序员,自然想通过更简单的方式来解放右手。办法总比困难多。

从前面我们知道,通过继承 AppCompactActivity 这种实现方式中核心就是向 Activity 中注入一个空的 Fragment–ReportFragment。我们能不能也通过这种方式,动态的向 Activity 中注入这个 ReportFragment 呢?

答案是行的,而且google已经帮我们实现了。

Google 为我们提供了一个extensions库,我们需要单独引入:

implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
复制代码

引入该库之后,我们的使用方式,就跟继承自 AppCompactActivity 基本相同,唯一的不同点就是我们需要自己实现 LifecycleOwner ,提供一个LifecycleRegistry(不要担心,一行代码,直接用现成的就好)

public class MyActivity extends Activity implements LifecycleOwner {
    private LifecycleRegistry lifecycleRegistry;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        lifecycleRegistry = new LifecycleRegistry(this);
        // 不再需要手动调用 markstate方法了
        //lifecycleRegistry.markState(Lifecycle.State.CREATED);
    }

    @Override
    public void onStart() {
        super.onStart();
        // 不再需要手动调用 markstate方法了
       	// lifecycleRegistry.markState(Lifecycle.State.STARTED);
    }

    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return lifecycleRegistry;
    }
}
复制代码

是不是很神奇,这是如何实现的呢,我们顺着代码反推下:

我们Command/Ctrl+鼠标左键,点击ReportFragment,会发现使用到它的有两个类:LifecycleDispatcher.javaProcessLifecycleOwner.java这两个类,而这二者,就是extensions这个库下的类。

那我们就先追踪ReportFragment.injectIfNeededIn(activity)LifecycleDispatcher.java类中的调用:

class LifecycleDispatcher {

    static class DispatcherActivityCallback extends EmptyActivityLifecycleCallbacks {

        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            ReportFragment.injectIfNeededIn(activity);
        }

        @Override
        public void onActivityStopped(Activity activity) {
        }

        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
        }
    }

    private LifecycleDispatcher() {
    }
}
复制代码

ReportFragment.injectIfNeededIn(activity) 这行代码是在 LifecycleDispatcher 的静态内部类DispatcherActivityCallback的 onActivityCreated(…) 方法中调用的。而DispatcherActivityCallback又继承自EmptyActivityLifecycleCallbacksEmptyActivityLifecycleCallbacks是啥?它其实就是Application.ActivityLifecycleCallbacks接口的空实现类。

class EmptyActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    }

    @Override
    public void onActivityStarted(Activity activity) {
    }

    @Override
    public void onActivityResumed(Activity activity) {
    }

    @Override
    public void onActivityPaused(Activity activity) {
    }

    @Override
    public void onActivityStopped(Activity activity) {
    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    }

    @Override
    public void onActivityDestroyed(Activity activity) {
    }
}
复制代码

继续回到上面的 LifecycleDispatcher 的源码查看,发现静态内部类 DispatcherActivityCallback 的实例化是在LifecycleDispatcher类的static方法init()中,在该方法中进行监听器的注册:

class LifecycleDispatcher {

    private static AtomicBoolean sInitialized = new AtomicBoolean(false);

    static void init(Context context) {
        if (sInitialized.getAndSet(true)) {
            return;
        }
        ((Application) context.getApplicationContext())
                .registerActivityLifecycleCallbacks(new DispatcherActivityCallback());
    }

   //...
}
复制代码

这里面,就真正的看到了通过ApplicationregisterActivityLifecycleCallbacks来注册监听器。

继续追踪LifecycleDispatcher#init(...)方法在哪调用的,就进入了ProcessLifecycleOwnerInitializer类的onCreate()方法:

public class ProcessLifecycleOwnerInitializer extends ContentProvider {
    @Override
    public boolean onCreate() {
        LifecycleDispatcher.init(getContext());
        ProcessLifecycleOwner.init(getContext());
        return true;
    }
	//...
}
复制代码

ProcessLifecycleOwnerInitializer是继承自ContentProvider,在其 onCreate() 方法中,进行了LifecycleDispatcher 的初始化,并且也进行了ProcessLifecycleOwner 的初始化。关于ProcessLifecycleOwner ,后文有介绍。

通过看源码,发现它对 ContentProvider 的各种方法都进行了空实现。其实,这里就是利用了 ContentProvider 的隐式加载。它的 onCreate() 方法执行时机是在Application#onCreate()方法之前。这样它就能通过 Application 来监听 Activity 的创建,并判断是否已经添加过了一个空UI的 ReportFragment。若没有,就进行添加。这种设计真的是太妙了。

这里 ContentProvider 之于 Application 的作用就类似于 Headless Fragment 之于 Activity 一样,目的都是避免继承系统组件。关于 ContentProvider 的生命周期可以看 android – ContentProvider destruction/lifecycle – Stack Overflow

我们知道,四大组件都是要在 AndroidManifest.xml 文件中进行生命的。那这个 ContentProvider 类型的 ProcessLifecycleOwnerInitializer 又是在什么时候声明的呢?

我们找到extensions库,通过如下方式查看它的下载位置:

Android Studio 切换到 Project 模式,在External Libraries中找到这个类所在的位置,右键下图箭头所指classes.jar 选择在本地显示。

image.png

在这个jar的上级目录下 有个AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="androidx.lifecycle.process" >
    <uses-sdk android:minSdkVersion="14" />
    <application>
        <provider
            android:name="androidx.lifecycle.ProcessLifecycleOwnerInitializer"
            android:authorities="${applicationId}.lifecycle-process"
            android:exported="false"
            android:multiprocess="true" />
    </application>
</manifest>
复制代码

在这里我们果真找到了声明。

这里的AndroidManifest.xml最终会合并入我们app moduleAndroidManifest.xml文件中。

反推结束,我们再反过来梳理一遍:

  1. 在清单文件注册的ProcessLifecycleOwnerInitializer,这个provider在onCreate中调用了 LifecycleDispatcher.init(getContext())

  2. LifecycleDispatcher.init(getContext())方法调用了((Application) context.getApplicationContext()).registerActivityLifecycleCallbacks(new DispatcherActivityCallback());

  3. DispatcherActivityCallback中的onActivityCreated中调用了
    ReportFragment.injectIfNeededIn ;

  4. ReportFragment.injectIfNeededIn方法把ReportFragment的各个生命周期中调用了加入到我们activity中

  5. ReportFragment的各个生命周期中调用了它的dispatch()方法。

  6. dispatch()调用了LifecycleRegister的handleLifecycleEvent()

三个情况都分析完了,最后大家都是调用LifecycleRegister的handleLifecycleEvent()

所以我们接下来分析LifecycleRegistry

LifecycleRegistry继承自Lifecycle

我们可以先看下Lifecycle

参考

使用能感知生命周期的组件来处理生命周期

初学 Android 架构组件之 Lifecycle

Android官方架构组件Lifecycle:生命周期组件详解&原理分析

Jetpack中的Lifecycle

Android arch components 源码分析(2)—— Lifecycle

Android Architecture Component — Lifecycle 浅析

生命周期组件 Lifecycle 源码解析(一)

生命周期组件 Lifecycle 源码解析(二)

Android架构之美-Lifecycle

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享