IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Jetpack Lifecycle使用及原理解析 -> 正文阅读

[移动开发]Jetpack Lifecycle使用及原理解析

笔者准备深入学习 Jetpack 系列的 Android Architecture Components 中的一些列组件,记录一下学习过程,本文是 Lifecycle 的使用及原理解析,通过一个实际的例子,来体验 Lifecycle 能给我们带来哪些不一样的功能?最后通过阅读 Lifecycle 的源码,由浅入深一步一步探索其原理!

Lifecycle 简介

Lifecycle 提供了可用于构建生命周期感知型组件的类和接口,可以感知 Activity、Fragment 的生命周期并根据 Activity、Fragment 的当前生命周期状态在其相应的回调事件中调整其自身的行为,能有效的避免内存泄漏。

1.Lifecycle 的使用

1.1 新建 LifecycleObserver

首先创建一个接口去实现 DefaultLifecycleObserver,然后重写其生命周期回调方法,这样观察者就创建完毕,之后就可以观察 Activity、Fragment 的生命周期改变。
DefaultLifecycleObserver 继承自 FullLifecycleObserver,FullLifecycleObserver 继承自 LifecycleObserver,我们也可以直接创建一个接口去实现 LifecycleObserver,不过 Google 官方更推荐我们使用 DefaultLifecycleObserver 接口。

class MyLifecycleObserver : DefaultLifecycleObserver {
    override fun onCreate(owner: LifecycleOwner) {
        super.onCreate(owner)
        Log.e(TAG, "onCreate: ")
    }

    override fun onStart(owner: LifecycleOwner) {
        super.onStart(owner)
        Log.e(TAG, "onStart: ")
    }

    override fun onResume(owner: LifecycleOwner) {
        super.onResume(owner)
        Log.e(TAG, "onResume: ")
    }

    override fun onPause(owner: LifecycleOwner) {
        super.onPause(owner)
        Log.e(TAG, "onPause: ")
    }

    override fun onStop(owner: LifecycleOwner) {
        super.onStop(owner)
        Log.e(TAG, "onStop: ")
    }

    override fun onDestroy(owner: LifecycleOwner) {
        super.onDestroy(owner)
        Log.e(TAG, "onDestroy: ")
    }

    companion object {
        private const val TAG = "MyLifecycleObserver"
    }
}

1.2 添加 LifecycleObserver 观察者

在项目的 BaseActivity 的 onCreate( ) 方法中将 MyLifecycleObserver 添加进来。

open class BaseActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // Lifecycle是被观察者,通过addObserver的方式添加 LifecycleObserver 观察者
        // 然后在 Activity 执行到对应生命周期的时候通知这个观察者
        // 分析1
        lifecycle.addObserver(MyLifecycleObserver())
    }
}

1.3 小结

基本使用还是挺简单的,每次当 Activity 执行到对应的生命周期改变,MyLifecycleObserver 就会执行对应的回调方法,这里只是简单的输出日志。

2.Lifecycle 原理解析

2.1 Lifecycle 的获取

分析1 – 跟踪源码一步步分析,Activity 如何获取到的 Lifecycle ?
我们查看 Activity、Fragment 的源码,发现他们都默认实现了 LifecycleOwner 接口,并在getLifecycle() 方法返回的是 LifecycleRegistry 对象,此时 Activity、Fragment 类中分别持有了 Lifecycle,LifecycleRegistry 是 Lifecycle 抽象类的具体实现,这个类随着 Activity、Fragment 的创建而创建。

@SuppressWarnings({"WeakerAccess", "unused"})
public interface LifecycleOwner {
    /**
     * Returns the Lifecycle of the provider.
     * 生命周期持有者,返回一个 Lifecycle 对象
     */
    @NonNull
    Lifecycle getLifecycle();
}
public class ComponentActivity extends androidx.core.app.ComponentActivity implements LifecycleOwner,... {
	// 初始化 LifecycleRegistry
	private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
	// 返回 Lifecycle
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
}

public class Fragment implements LifecycleOwner,... {

	private final LifecycleRegistry mLifecycleRegistry;

    public Fragment() {
    	// 初始化 LifecycleRegistry
        initLifecycle();
    }
	// 初始化 LifecycleRegistry
    private void initLifecycle() {
        mLifecycleRegistry = new LifecycleRegistry(this);
    }
    // 返回 Lifecycle
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
}

2.2 Lifecycle 添加观察者

LifecycleRegistry 类中,通过 addObserver( ) 方法将 LifecycleObserver 进行包装并添加到 mObserverMap 这个集合中。
使用 ObserverWithState 类(下文有具体介绍)将观察者对象和状态进行包装,然后存储在 FastSafeIterableMap 中。

	@Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        enforceMainThreadIfNeeded("addObserver");
        // 初始状态
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        // 通过 ObserverWithState 将观察者和状态进行包装
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
        // 将包装类放到 FastSafeIterableMap<LifecycleObserver, ObserverWithState> 中
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
        ............
        // 将状态进行对齐,在添加观察者的时候,可能是在任何状态的时候进行添加的,
        // lifecycle需要将这个状态进行对齐。例如我们在 onResume 的回调中添加了观察者,
        // 此时我们的观察者就收到依次收到 onCreate,onStart,onResume 的回调。
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
            final Event event = Event.upFrom(statefulObserver.mState);
            if (event == null) {
                throw new IllegalStateException("no event up from " + statefulObserver.mState);
            }
            statefulObserver.dispatchEvent(lifecycleOwner, event);
            popParentState();         
            targetState = calculateTargetState(observer);
        }
 
        if (!isReentrance) {
        	// we do sync only on the top level.
            // 同步状态 
            sync();
        }
        mAddingObserverCounter--;
    }

2.3 ReportFragment 类

通过上面两步,有了被观察者 Lifecycle,也给 Lifecycle 添加了观察者 LifecycleObserver,那我们的观察者是怎样感知到 Activity、Fragment 的生命周期的呢?

这里以 Activity 为切入点,在其 onCreate( ) 方法中,添加一个没有界面的 ReportFragment 来实现的,当 ReportFragment 的生命周期方法被调用时,就会触发其宿主 Activity 的 Lifecycle 的生命周期事件分发方法的调用。

public class ComponentActivity extends xxx implements LifecycleOwner,xxx {
	@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 初始化了一个 ReportFragment,将 ReportFragment 注册到 Activity 中
        // 其作用就是用来分发生命周期状态的
        // 分析2
        ReportFragment.injectIfNeededIn(this);
    }
}
public class ReportFragment extends Fragment {

	public static void injectIfNeededIn(Activity activity) {
        if (Build.VERSION.SDK_INT >= 29) {
            // On API 29+, we can register for the correct Lifecycle callbacks directly
            // API29以上的是通过注册一个 LifecycleCallbacks 来监听 Activity 的生命周期变化的。
            LifecycleCallbacks.registerIn(activity);
        }
        // Prior to API 29 and to maintain compatibility with older versions of
        // ProcessLifecycleOwner (which may not be updated when lifecycle-runtime is updated and
        // need to support activities that don't extend from FragmentActivity from support lib),
        // use a framework fragment to get the correct timing of Lifecycle events
        // 创建了一个 ReportFragment 添加到 Activity 的 FragmentManager 中。
        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();
        }
    }	

    @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);
            }
        }
    }
}

分析2 – 在 ReportFragment 中的各个生命周期都调用了dispatch(Lifecycle.Event event) 方法,传递了不同的 Event 的值,这个就是在 Activity、Fragment 的各个生命周期回调时,Lifecycle 所要处理的生命周期方法。
dispatch(Lifecycle.Event event) 方法中最终都是调用了((LifecycleRegistry) lifecycle).handleLifecycleEvent(event) 方法,进行生命周期状态的分发。

2.4 LifecycleRegistry ## handleLifecycleEvent() 方法

    public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
        enforceMainThreadIfNeeded("handleLifecycleEvent");
        // 分析3 -- event.getTargetState();
        // 分析4 -- moveToState
        moveToState(event.getTargetState());
    }

分析3 – 根据当前 Lifecycle.Event 的值,其实也就是 Activity、Fragment 生命周期回调的值,来获取下一个 Lifecycle.State 的状态,即 Lifecycle 将要到什么状态。

2.4.1 Lifecycle 内部的枚举类 Event ## getTargetState() 方法
	@NonNull
    public State getTargetState() {
        switch (this) {
            case ON_CREATE:
            case ON_STOP:
                return State.CREATED;
            case ON_START:
            case ON_PAUSE:
                return State.STARTED;
            case ON_RESUME:
                return State.RESUMED;
            case ON_DESTROY:
                return State.DESTROYED;
            case ON_ANY:
                break;
        }
        throw new IllegalArgumentException(this + " has no target state");
    }	

在这里插入图片描述
对照上图(借用,文末有链接)分析一下 getTargetState() 在各个生命周期回调时,Lifecycle.Event 的生命周期状态对 Lifecycle.State 的当前状态的取值,整个状态趋势是分为:正在可见和正在不可见。

2.4.2 LifecycleRegistry ## moveToState() 方法
	private void moveToState(State next) {
        if (mState == next) {
            return;
        }
        mState = next;
        if (mHandlingEvent || mAddingObserverCounter != 0) {
            mNewEventOccurred = true;
            // we will figure out what to do on upper level.
            return;
        }
        mHandlingEvent = true;
        // 分析5
        sync();
        mHandlingEvent = false;
    }

分析4 – moveToState() 方法中,记录 Lifecycle 将要到什么状态,然后会执行 sync() 方法进行同步操作。

2.4.3 LifecycleRegistry ## sync() 方法
	// happens only on the top of stack (never in reentrance),
    // so it doesn't have to take in account parents
    private void sync() {
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            throw new IllegalStateException("LifecycleOwner of this LifecycleRegistry is already"
                    + "garbage collected. It is too late to change lifecycle state.");
        }
        // 分析6 -- isSynced()方法
        while (!isSynced()) {
            mNewEventOccurred = false;
            // no need to check eldest for nullability, because isSynced does it for us.
            if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
            	// 分析7 -- 向正在不可见方向
                backwardPass(lifecycleOwner);
            }
            Map.Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
            if (!mNewEventOccurred && newest != null
                    && mState.compareTo(newest.getValue().mState) > 0) {
                // 分析8 -- 向正在可见方向
                forwardPass(lifecycleOwner);
            }
        }
        mNewEventOccurred = false;
    }

	// 分析6 -- isSynced()方法
    // 当 mObserverMap 中存储的最新的状态(刚插入的)与最老的状态(最先插入的)一致,
    // 并且当前状态等于最新的状态,则返回值为 true,即不用做状态的同步,因为已经同步了。
    // 若不一致或当前状态不等于最新的状态,则返回值为 false,即需要做状态同步,向前或向后调整。
    private boolean isSynced() {
        if (mObserverMap.size() == 0) {
            return true;
        }
        State eldestObserverState = mObserverMap.eldest().getValue().mState;
        State newestObserverState = mObserverMap.newest().getValue().mState;
        return eldestObserverState == newestObserverState && mState == newestObserverState;
    }

分析5 – 首先判断状态是否同步,如果状态不同步,在这里会通过当前的状态 mState 和 mObserverMap 中存储的eldest 和 newest 的状态进行比较操作,判断当前流程是向正在可见发展还是正在向不可见发展。

例如:当前执行的状态是 START,与上个状态相比,如果上个状态是CREATE,相比结果就是>0 ,说明是正在可见;如果上个状态是RESUME ,相比结果<0 ,说明是正在不可见。

根据判断结果,分别执行不同的操作,backwardPass() 和 forwardPass()。backwardPass() 是不可见方向还原,也就是上图的向左指向的箭头方向,forwardPass() 是以可见方向还原,也就是上图的向右指向的箭头方向。

2.5 ObserverWithState ## dispatchEvent() 方法

分析7分析8 – 都是走到 ObserverWithState 类的 dispatchEvent() 方法,在前面我们看到过这个类,在给 Lifecycle 添加观察者时即 addObserver() 时初始化的。

ObserverWithState 是对观察者对象和状态进行了一个包装,内部两个成员属性,State:状态和 LifecycleEventObserver:观察者。

LifecycleEventObserver 是一个接口,它继承了 LifecycleObserver 接口。

    static class ObserverWithState {
        State mState;
        LifecycleEventObserver mLifecycleObserver;

        ObserverWithState(LifecycleObserver observer, State initialState) {
        	// 分析9 -- 获取 LifecycleEventObserver 实例对象
        	// 由 addObserver() 添加进来的 DefaultLifecycleObserver,最后获取到的是 FullLifecycleObserverAdapter 实例对象
            mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
            mState = initialState;
        }

        void dispatchEvent(LifecycleOwner owner, Event event) {
            State newState = event.getTargetState();
            mState = min(mState, newState);
            // 分析10 -- 回调 FullLifecycleObserverAdapter 的 onStateChanged() 方法
            mLifecycleObserver.onStateChanged(owner, event);
            mState = newState;
        }
    }

分析9 – Lifecycling.lifecycleEventObserver(observer) 方法,入参为我们 addObserver() 添加进来的 DefaultLifecycleObserver,返回一个对应类型的实例化对象,我们自定义的观察者,实现的是 DefaultLifecycleObserver 接口,DefaultLifecycleObserver 接口又继承了 FullLifecycleObserver ,所以这里会新建一个 FullLifecycleObserverAdapter 对象,并返回。

2.6 Lifecycling ## lifecycleEventObserver() 方法

    @NonNull
    static LifecycleEventObserver lifecycleEventObserver(Object object) {
        boolean isLifecycleEventObserver = object instanceof LifecycleEventObserver;
        // 我们自定义的观察者,实现的是 DefaultLifecycleObserver 接口,
        // DefaultLifecycleObserver 接口又继承了 FullLifecycleObserver
        // 所以这里值为 true
        boolean isFullLifecycleObserver = object instanceof FullLifecycleObserver;
        if (isLifecycleEventObserver && isFullLifecycleObserver) {
            return new FullLifecycleObserverAdapter((FullLifecycleObserver) object,
                    (LifecycleEventObserver) object);
        }
        if (isFullLifecycleObserver) {
        	// 新建一个 FullLifecycleObserverAdapter 对象,并返回。
            return new FullLifecycleObserverAdapter((FullLifecycleObserver) object, null);
        }

        if (isLifecycleEventObserver) {
            return (LifecycleEventObserver) object;
        }

        final Class<?> klass = object.getClass();
        int type = getObserverConstructorType(klass);
        if (type == GENERATED_CALLBACK) {
            List<Constructor<? extends GeneratedAdapter>> constructors =
                    sClassToAdapters.get(klass);
            if (constructors.size() == 1) {
                GeneratedAdapter generatedAdapter = createGeneratedAdapter(
                        constructors.get(0), object);
                return new SingleGeneratedAdapterObserver(generatedAdapter);
            }
            GeneratedAdapter[] adapters = new GeneratedAdapter[constructors.size()];
            for (int i = 0; i < constructors.size(); i++) {
                adapters[i] = createGeneratedAdapter(constructors.get(i), object);
            }
            return new CompositeGeneratedAdaptersObserver(adapters);
        }
        return new ReflectiveGenericLifecycleObserver(object);
    }

在 Lifecycling.lifecycleEventObserver(observer) 这个方法中,会将 LifecycleObserver 对象包装成LifecycleEventObserver 的各种实现类:

  • List itemFullLifecycleObserverAdapter
  • LifecycleEventObserver
  • SingleGeneratedAdapterObserver
  • CompositeGeneratedAdaptersObserver
  • ReflectiveGenericLifecycleObserver

2.7 FullLifecycleObserverAdapter 类

分析10 – ObserverWithState 类的 dispatchEvent() 方法,调用了mLifecycleObserver.onStateChanged(owner, event),这里其实调用的是 FullLifecycleObserverAdapter 的 onStateChanged 方法。然后在 onStateChanged 方法中我们自定义的观察者就可以接收到生命周期的回调了。

class FullLifecycleObserverAdapter implements LifecycleEventObserver {

    private final FullLifecycleObserver mFullLifecycleObserver;
    private final LifecycleEventObserver mLifecycleEventObserver;

    FullLifecycleObserverAdapter(FullLifecycleObserver fullLifecycleObserver,
            LifecycleEventObserver lifecycleEventObserver) {
        mFullLifecycleObserver = fullLifecycleObserver;
        mLifecycleEventObserver = lifecycleEventObserver;
    }

    @Override
    public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
        switch (event) {
            case ON_CREATE:
                mFullLifecycleObserver.onCreate(source);
                break;
            case ON_START:
                mFullLifecycleObserver.onStart(source);
                break;
            case ON_RESUME:
                mFullLifecycleObserver.onResume(source);
                break;
            case ON_PAUSE:
                mFullLifecycleObserver.onPause(source);
                break;
            case ON_STOP:
                mFullLifecycleObserver.onStop(source);
                break;
            case ON_DESTROY:
                mFullLifecycleObserver.onDestroy(source);
                break;
            case ON_ANY:
                throw new IllegalArgumentException("ON_ANY must not been send by anybody");
        }
        if (mLifecycleEventObserver != null) {
            mLifecycleEventObserver.onStateChanged(source, event);
        }
    }
}

3.Lifecycle 总结

3.1 Lifecycle 是怎样获取到的?

由 Activity、Fragment 的源码,可知他们都默认实现了 LifecycleOwner 接口,并在getLifecycle() 方法返回的是 LifecycleRegistry 对象,此时 Activity、Fragment 类中分别持有了 Lifecycle,LifecycleRegistry 是 Lifecycle 抽象类的具体实现,这个类随着 Activity、Fragment 的创建而创建。

3.2 Lifecycle 是怎样感知生命周期的?

是在 ReportFragment 中的各个生命周期都调用了dispatch(Lifecycle.Event event) 方法,传递了不同的 Event 的值.

3.3 Lifecycle 是如何处理生命周期的?

通过调用了 ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event) 方法,也就是LifecycleRegistry 类来处理这些生命周期。

3.4 为什么 LifecycleObserver 可以感知到 Activity 的生命周期?LifecycleObserver 的方法是怎么回调的呢?

LifecycleRegistry 的 handleLifecycleEvent方法,通过当前事件状态,判断是否需要做同步处理,如果需要,则分情况看是向前还是向后同步,最后都是走到 ObserverWithState 类的 dispatchEvent() 方法,在方法内部会根据 addObserver() 方法传入的 LifecycleObserver 的各种子类,生成不同的 LifecycleEventObserver 实例对象,并回调 LifecycleEventObserver 的 onStateChanged() 方法,onStateChanged() 方法内部会调用 LifecycleObserver 的实现类的对应的回调方法;

3.5 为什么 Google 官方更推荐我们使用 DefaultLifecycleObserver 接口?

我们本篇文章分析的是继承自 DefaultLifecycleObserver 来实现 LifecycleObserver 观察者的,这是因为 Google 已经帮我们基于 DefaultLifecycleObserver 做了很多封装,不用我们自己去实现了。如果我们自己继承自 LifecycleObserver 来实现观察者,则需要通过注解、反射等一系列处理,最终回调到依赖于反射的 LifecycleObserver 。也就是上面的 分析9 – 将会返回 ReflectiveGenericLifecycleObserver 实例对象,并通过方法的反射调用相应的生命周期回调方法。

4.参考大佬

AboBack:Android Jetpack组件Lifecycle基本使用和原理分析

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-05-11 16:33:45  更:2022-05-11 16:34:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 1:40:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码