lifecycle安卓(Android开发 :Fragment懒加载的几种方式与性能对比)

2024-07-23 12:04:55 3

lifecycle安卓(Android开发 :Fragment懒加载的几种方式与性能对比)

本文目录

Android开发 :Fragment懒加载的几种方式与性能对比

TabLayout+ViewPager+Fragment是我们开发常用的组合。ViewPager的默认机制就是把全部的Fragment都加载出来,而为了保障一些用户体验,我们使用懒加载的Fragment,就是让我们再用户可见这个Fragment之后才处理业务逻辑。

而我们在一些设备或版本中可能就出现懒加载失效的问题。其实谷歌早就把一些懒加载的方案都标记弃用了,我们一直都用的老的随时会失效的Api。万一哪天彻底失效了就会导致线上事故。

接下来我们就看看Fragment的懒加载是如何演变的。谷歌又是推荐我们如何使用的。

在AndroidX还没出来的时候,大家的懒加载应该都是这样。判断setUserVisibleHint的方法,当用户可见的时候才回调方法去加载逻辑。

例如的我封装:

使用的示例:

扩展方法:

Fragment:

到此就实现了onLazyInitData的回调,只有出现Fragment显示在前台的时候才会调用方法,执行逻辑。

每次判断 setUserVisibleHint 和 onHiddenChanged 也麻烦,并且他们并不稳定,我也遇到过不回调的时候。

Android出来之后,给 FragmentStatePagerAdapter 添加了一个 @Behavior int behavior 的参数。

其本质就是内部帮你处理和切换MaxLifecycle:

如何使用呢:

之前的扩展方法以及预留了 behavior 参数,当为1的时候就不会回调 setUserVisibleHint 方法了,我们直接监听 OnResume 即可。

注意这个页面继承的就不是我们自定义的懒加载Fragment了。普通的Fragment 回调 onResume 即可。

ViewPager2出来之后。我们的 FragmentStatePagerAdapter 退出历史舞台。

即便能用,即便效果还是和ViewPage2的效果一样,但是还是标记废弃了。具体原因我也不知道,据说是因为老版本会出现问题导致数据丢失,页面空白。

ViewPage2我们都知道内部是通过RV实现的。但是对于Fragment的处理有单独的Adapter实现。

扩展方法:

使用:

使用的方式和ViewPager差不多,这里的Fragment也是使用普通的Fragment即可。

内存占用分别取三组数据

ViewPager数据

ViewPager2数据

结论 ViewPager2基于RV实现的效果还是比老版ViewPager要骚好一点。

并且老版本标记废弃,大家如果是用ViewPager2的话,还是推荐使用ViewPager2实现。如果大家还是用的老版本的ViewPager也推荐使用behavor参数。使用 onResume 实现懒加载的实现。以后再换到ViewPager2的话,可以无缝切换过来。

说明一下,测试数据仅供参考,毕竟我也不是专业测试,测试数据源也不不多。如有不对的地方,也望大家指正。

Android-Lifecycle原理解析

Event触发的时机:

而在androidx.activity.ComponentActivity和androidx.core.app.ComponentActivity中,该方法的实现,其实都是一样的。

但是这两个Activity,其实都有自己的mLifecycleRegistry对象。

LifecycleRegistry对象其实可以理解为观察者模式中的Observable,也就是被观察者,而LifecycleRegistry对象的创建,其实是传入一个LifecycleOwner实现类对象,而androidx.activity.ComponentActivity和androidx.core.app.ComponentActivity实现了LifecycleOwner接口,所以传入的是this。

LifecycleRegistry中聚合了多个LifecycleObserver,生命周期改变时,通知LifecycleObserver进行相应方法的调用。 在LifecycleRegistry类中的addObserver方法中,其实就是通过封装LifecycleObserver生成了一个ObserverWithState对象,然后放入FastSafeIterableMap中,而FastSafeIterableMap其实就是一个自定义列表,用于保存观察者并且可在遍历期间处理删除/添加。 其实在自定义的某个类去实现LifecycleObserver接口的时候,在activity中,是需要通过getLifecycle().addObserver()进行注册的,这个过程其实就是调用了LifecycleRegistry的addObserver()方法。

ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);会将LifecycleObserver对象封装在ReflectiveGenericLifecycleObserver对象中。但是这里的需要判断是实现了哪个接口,比如androidx.activity.ComponentActivity中的构造函数中,因为是直接new LifecycleEventObserver匿名内部类实现接口对象,则isLifecycleEventObserver为true,就不会new ReflectiveGenericLifecycleObserver(),而在自定义一个类的时候,一般实现LifecycleObserver接口,则就会new ReflectiveGenericLifecycleObserver()

androidx.activity.ComponentActivity的构造函数:这里是new LifecycleEventObserver

自定义的BasePresenter:这里是实现LifecycleObserver接口

所以上面的两种不同的实现,BasePresenter实现的是LifecycleObserver,所以这个LifecycleObserver的最终实现是ReflectiveGenericLifecycleObserver。而ComponentActivity因为是new LifecycleEventObserver,所以这个匿名内部类对象就是最终实现。

在androidx.core.app.ComponentActivity的onCreate方法中,会调用

这里使用ReportFragment,如果是api29以及以上的,则可以直接注册回调来获取Activity的生命周期回调。如果是api29以下的,则需要手动给Activity添加一个空白的Fragment,类似于Glide监听生命周期回调的做法。

LifecycleCallbacks的定义如上,是在ReportFragment中定义的,其实就是使用了Application.ActivityLifecycleCallbacks来实现了。 其实就是在androidx.core.app.ComponentActivity中添加一个ReportFragment,而ReportFragment的生命周期方法,其实都调用了一个dispatch方法。

所以在ReportFragment的生命周期方法,其实就会通过调用对应的dispatch方法进而调用到了Activity的getLifecycle()方法获取到一个LifecycleRegistry对象,然后调用LifecycleRegistry的handleLifecycleEvent()方法。

这里需要事先获取到Activity的下一个生命周期状态,而这个状态过程其实与Fragment的类似,都是先升序,然后再降序的一个过程。即ON_CREATE是CREATED,ON_RESUME是RESUMED,然后ON_PAUSE是变成STARTED

而上面调用的sync()方法,其实其内部会调用两个方法backwardPass()和forwardPass(),一个是逆推,一个是顺推,其实就是可以认为一个是正序,一个是倒序。 比如forwardPass(),其实其内部就是遍历刚才缓存Observer的集合,找到每个Observer

而这里的dispatchEvent,其实就是ObserverWithState的方法,因为ObserverWithState内部封装了LifecycleEventObserver对象,而LifecycleEventObserver对象又是封装了LifecycleObserver对象的。

比如Activity的,其实onStateChanged是在androidx.activity.ComponentActivity的构造器中添加注册的LifecycleEventObserver监听接收对应的处理回调,在这里就会根据是ON_STOP还是ON_DESTROY进行回调的处理,也就是生命周期的处理。 这样的生命周期回调,在自定义类实现LifecycleObserver接口的时候,也可以采用注解的方式注册对应的LifecycleEventObserver监听,这样的生命周期的回调,其实就是回调到对应的注解和事件的方法中。这样是采用了类似于apt注解处理器的方式,生成了对应的java类

这里需要注意,如果是自定义添加监听的时候,是实现了LifecycleEventObserver,那么在分发的时候,调用ObserverWithState的dispatchEvent方法去分发,就会直接回调到了自定义LifecycleEventObserver实现类中的onStateChanged中;而如果是使用LiveData添加观察者的话,则是封装成LifecycleBoundObserver对象,然后通过其onStateChanged方法继续进一步的处理分发,调用到对应的Observer的onChanged方法进行最终的处理

如果这里的分发是分发到上面的那个自定义的BasePresenter,则需要经过ReflectiveGenericLifecycleObserver

从上面的原理解析,可以知道,Lifecycle的生命周期的感知和分发,其实也是依赖于一个ReportFragment,这其实也是一个空的Fragment,这样的做法,其实与Glide的生命周期的监听是类似的做法,都是采用一个空的Fragment来监听生命周期的变化,然后在不同的生命周期做不同的操作。

Android Lifecycle源码解析

 Lifecycle是生命周期的意思。它是Jetpack中的一个 生命周期感知型组件 ,可执行操作来感知响应另一个组件(如 Activity 和 Fragment)的生命周期状态的变化。

 1.第一步添加依赖

 2.实现LifecycleObserver接口以及添加注解

 3.在Activity中或者Fragment中调用lifecycle.addObserver方法,把LifecycleObserver传入进去就可以

使用是不是很简单,在MytViewModelLifecycle里面就可以监听到Activity中或者Fragment生命周期了

 1.首先分析lifecycle怎么来的   lifecycle调用的是ComponentActivity的getLifecycle方法,返回了一个mLifecycleRegistry

那么我们就从ComponentActivity入手会实现了它LifecycleOwner接口,并且初始化了LifecycleRegistry

  2.addObserver分析   上面了解了lifecycle的实例,那么我们就从LifecycleRegistry入手,首先看addObserver方法,我们只管传入的参数哪里去了,也就是说我们只需要看ObserverWithState做了什么事.   ObserverWithState会调用Lifecycling.lifecycleEventObserver方法,然后创建ReflectiveGenericLifecycleObserver对象,然后调用ClassesInfoCache.sInstance.getInfo,这个方法传入的是我们的MytViewModelLifecycle的对象,拿到他的class,然后通过反射拿到MytViewModelLifecycle方法和注解并且存入map.具体怎么反射这里就不细讲了! (在反射中一般都是通过map去存取提高性能)

 3.观察者(MytViewModelLifecycle)是如何知道被观察者(Activity)的生命周期的    回到ComponentActivity中的onCreate方法,它会创建一个空白的ReportFragment,有了这个ReportFragment,当activity执行生命周期ReportFragment也会执行相应的生命周期. 我们以onStart为例,每个生命周期都会调用dispatch方法,最终都会调用**dispatch( Activity activity, Lifecycle.Event event)方法. 然后调用((LifecycleRegistry) lifecycle).handleLifecycleEvent(event)方法

  在handleLifecycleEvent分别会调用getStateAfter和moveToState方法这两个方法,getStateAfter的目的就是通过生命周期得到一个状态.方便大家理解大家可以看白色背景的那张图.通过不同的事件拿到相应的状态  1.初始化状态-》页面显示状态,这种情况属于activity的创建到显示 这属于前进状态  2.页面显示状态-》销毁状态:这种情况下属于activity回到不可见了 这属于倒退状态

  moveToState(next):这个方法的意思就是状态对齐.举个栗子吧:假如activity(被观察者)现在是onstart状态,这时候观察者MytViewModelLifecycle还是CREATE状态,这时候为了保证生命周期对齐,所以需要将next赋值给State,接着调用sync()进行同步

   backwardPass方法 如果满足条件的主要调用downEvent 这个方法主要通过状态拿到事件,例如现在是STARTED对应上面的图拿到ON_STOP事件,然后又通过getStateAfter(ON_STOP)方法去拿到CREATED状态,

   LifecycleEventObserver是一个接口 然后ReflectiveGenericLifecycleObserver实现了这个接口,所以最终调用了ReflectiveGenericLifecycleObserver的onStateChanged方法

   invokeCallbacks方法里面通过反射拿到执行相应方法,这里就不多阐述了!

   再回到sync()里面的forwardPass方法 如果满足条件的主要调用upEvent(observer.mState)拿到前进状态,例如现在是STARTED状态就可以到ON_RESUME事件通过ON_RESUME事件最终通过反射调用@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)的方法

总结一下: 1.ComponentActivity里面实现了LifecycleOwner接口 ,并且初始化LifecycleRegistry了,LifecycleRegistry是实现了LifecycleOwner接口 2.在ComponentActivity里面创建了一个透明的ReportFragment来感应activity的生命周期,在Fragment的生命周期方法里面分别执行对应的dispatch方法 2.addObserver方法创建了ReflectiveGenericLifecycleObserver并且存储了观察者的class信息, 3.在dispatch传入相应的事件之后,然后通过getStateAfter拿到相应的状态 4.通过状态枚举比大小,如果是倒退流程就调用backwardPass方法,backwardPass方法会通过downEvent拿到状态拿到事件,然后又通过事件拿到状态 5.,如果是前进流程就调用forwardPass方法,forwardPass方法会通过upEvent拿到状态拿到事件 6.最后在ReflectiveGenericLifecycleObserver.onStateChanged里面执行mInfo.invokeCallbacks执行相应的方法 7.之所以要设计状态 是要留给其他框架用的

LottieAndroid使用详解及源码解析—轻而易举实现各种复杂动画

我们主要从以下四个方面来讲解:

1、 编译版本需要 27 2、所有的suport包版本需要27.1.0

3、如果有引入lifecycle,版本需要1.1.0

安卓开发:如何得知当前activity是被压入后台,还是跳转到新的activity

最近学习安卓开发activity的生命周期,对单个活动的生命周期较为熟悉。此时师兄抛出问题,当一个activity进入 onStop() 时,如何得知时由于用户点击了主页键,还是由于进入了另一个本程序的activity? 查阅网络资源后,得知可以通过安卓本身的多种方法来判断。不过某些方法的使用需要获取用户授权,或者需要较高版本的安卓系统。不过本文主要介绍通过activity本身的生命周期回调函数来判断。 由于设计两个activity的跳转,所以我们应该去考虑多个activity的生命周期回调函数顺序。查阅并测试可知,当进行activity跳转时,先执行原来activity的 onPause() 和,然后执行第二个activity的 onCreate() 、 onStart() 、 onResume() ,再执行第一个activity的 onStop 。如图所示,红色是第一个activity的回调函数执行,蓝色是第二个。我们可以利用这个特点,通过一个static变量来记录当前run的activity数量,当这个数量为0的时候,即程序被压入后台,当这个数量不为0,则表明当前执行了一个跳转操作。 首先新建一个 BaseActivity 类,声明一个static变量,让别的activity全部继承。并在 onStart() 和 onStop() 中修改 count 。 创建 MainActivity 类,继承自 BaseActivity 类,同时修改 onStop() ,检查 count 的值,判断此次导致 onStop() 的原因。我在这个activity中添加了一个button用于跳转到第二个activity。 这个类很简单,没有什么功能,只是跳转过来后,执行基类的 onCreate() 方法。 至此,我们便实现了通过activity生命周期回调函数判断是否被压入后台。不过,后来学长针对我的这种方式提出了漏洞——当引用外部SDK,且外部SDK中可以弹出未继承我们自定义的base基类的activity,那么怎么处理这种情况呢?这里就要用到安卓SDK提供的全局生命周期类了——Application.registerActivityLifecycleCallbaks,这里我们之后再谈。

lifecycle安卓(Android开发 :Fragment懒加载的几种方式与性能对比)

本文编辑:admin

更多文章:


如何让Windows 10系统桌面变得更好看?win10桌面的简单美化

如何让Windows 10系统桌面变得更好看?win10桌面的简单美化

大家好,如果您还对桌面美化不太了解,没有关系,今天就由本站为大家分享桌面美化的知识,包括如何让Windows 10系统桌面变得更好看的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!本文目录如何让Windows 10系统桌面

2024年7月26日 13:01

微信会员卡管理系统(微信会员卡是怎么实现的)

微信会员卡管理系统(微信会员卡是怎么实现的)

大家好,今天小编来为大家解答以下的问题,关于微信会员卡管理系统,微信会员卡是怎么实现的这个很多人还不知道,现在让我们一起来看看吧!本文目录微信会员卡是怎么实现的微信会员卡管理系统多少钱微信会员系统具体是怎么做的美发店微信会员卡管理系统如何做

2024年10月14日 19:35

msvcr100 dll放哪里(msvcp100.dll丢失怎么办放在哪里)

msvcr100 dll放哪里(msvcp100.dll丢失怎么办放在哪里)

本文目录msvcp100.dll丢失怎么办放在哪里msvcr100.dll放在哪里围攻》的msvcr100.dll文件应该放在哪个文件夹msvcr100.dll放哪里msvcp100.dll丢失怎么办放在哪里下载到该DLL文件后将msvcp

2024年6月3日 02:32

星际争霸2手游单机版下载中文版(《星际争霸2》怎么玩单机的)

星际争霸2手游单机版下载中文版(《星际争霸2》怎么玩单机的)

大家好,关于星际争霸2手游单机版下载中文版很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于《星际争霸2》怎么玩单机的的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下本站哦,希望对各位有所帮

2024年6月13日 03:24

图片编辑工具(编辑照片的软件哪个好)

图片编辑工具(编辑照片的软件哪个好)

各位老铁们,大家好,今天由我来为大家分享图片编辑工具,以及编辑照片的软件哪个好的相关问题知识,希望对大家有所帮助。如果可以帮助到大家,还望关注收藏下本站,您的支持是我们最大的动力,谢谢大家了哈,下面我们开始吧!本文目录编辑照片的软件哪个好有

2024年7月23日 07:21

手机键盘输入法下载(怎样设置手机键盘输入方式)

手机键盘输入法下载(怎样设置手机键盘输入方式)

大家好,手机键盘输入法下载相信很多的网友都不是很明白,包括怎样设置手机键盘输入方式也是一样,不过没有关系,接下来就来为大家分享关于手机键盘输入法下载和怎样设置手机键盘输入方式的一些知识点,大家可以关注收藏,免得下次来找不到哦,下面我们开始吧

2024年6月22日 02:49

天谕生活技能(天谕手游生活技能新手有几级)

天谕生活技能(天谕手游生活技能新手有几级)

本文目录天谕手游生活技能新手有几级最近在玩天谕,想做个休闲玩家,生活技能需要怎么练,我打算主攻裁缝,生活技能是不是也需要地区声望,裁天谕鲤鱼王用什么鱼饵天谕生活技能赚钱方法 天谕怎么用生活技天谕生活技能怎么练天谕副职业准考证在哪买天谕生活技

2024年1月1日 06:00

腾讯qq代码(腾讯qq错误代码116705是什么意思)

腾讯qq代码(腾讯qq错误代码116705是什么意思)

本文目录腾讯qq错误代码116705是什么意思QQ软件的代码有多少腾讯官方认证qq代码是多少腾讯QQ公司的股票代码是多少呢2012年6月腾讯QQ最新百分百能用的Q币代码qq代码怎么用qq版本各个版本的代码,我要包括现在最新的,谢谢~!腾讯q

2024年5月26日 20:07

我的世界不一样(我想问一下,为什么我的手机网易版我的世界和别人主页都不一样)

我的世界不一样(我想问一下,为什么我的手机网易版我的世界和别人主页都不一样)

本文目录我想问一下,为什么我的手机网易版我的世界和别人主页都不一样我要怎么下载不一样的我的世界为什么手机上的我的世界和有些主播玩的不一样,别的主播画质很好,我的就不好为什么我的世界和别人的不一样我的世界手机版和电脑版有什么不同网易我的世界电

2024年7月13日 16:54

弈城围棋水平对照表(围棋等级的划分,简单说一下就行)

弈城围棋水平对照表(围棋等级的划分,简单说一下就行)

各位老铁们,大家好,今天由我来为大家分享弈城围棋水平对照表,以及围棋等级的划分,简单说一下就行的相关问题知识,希望对大家有所帮助。如果可以帮助到大家,还望关注收藏下本站,您的支持是我们最大的动力,谢谢大家了哈,下面我们开始吧!本文目录围棋等

2024年7月28日 07:50

autocad2007画图教程(cad二维设计画图教程)

autocad2007画图教程(cad二维设计画图教程)

大家好,如果您还对autocad2007画图教程不太了解,没有关系,今天就由本站为大家分享autocad2007画图教程的知识,包括cad二维设计画图教程的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!本文目录cad二维设

2024年8月4日 12:55

腾讯首页qq(QQ与腾讯首页问题)

腾讯首页qq(QQ与腾讯首页问题)

本文目录QQ与腾讯首页问题打开QQ腾讯首页的问题为什么腾讯QQ首页无法显示QQ与腾讯首页问题如果你是会员的话才可以取消弹出迷你首页,不是的话只要你登陆就会自动弹出,如果关了想看的话可以点击如下图:QQ个人设置-系统设置-基本设置如果你是会员

2024年1月2日 12:00

网络安全教育知识(大学生网络安全知识有哪些)

网络安全教育知识(大学生网络安全知识有哪些)

“网络安全教育知识”相关信息最新大全有哪些,这是大家都非常关心的,接下来就一起看看网络安全教育知识(大学生网络安全知识有哪些)!本文目录大学生网络安全知识有哪些网络安全基础知识大全网络安全教育知识有哪些小学生应该如何进行网络安全教育网络安全

2024年9月27日 04:35

排超联赛积分榜(历届中超积分榜排名)

排超联赛积分榜(历届中超积分榜排名)

本篇文章给大家谈谈排超联赛积分榜,以及历届中超积分榜排名对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。本文目录历届中超积分榜排名中超联赛积分榜排名

2024年10月24日 11:45

s4 root教程(GALAXY S4 如何获取ROOT权限)

s4 root教程(GALAXY S4 如何获取ROOT权限)

本文目录GALAXY S4 如何获取ROOT权限三星GALAXYS4怎么获得ROOT权限怎样获取s4的root权限奇兔一键ROOT教程---三星S4获取ROOT权限的方法GALAXY S4 如何获取ROOT权限使用towelroot工具进行

2023年6月18日 15:00

公安交警官网 违章查询(交警网违章查询)

公安交警官网 违章查询(交警网违章查询)

其实公安交警官网 违章查询的问题并不复杂,但是又很多的朋友都不太了解交警网违章查询,因此呢,今天小编就来为大家分享公安交警官网 违章查询的一些知识,希望可以帮助到大家,下面我们一起来看看这个问题的分析吧!本文目录交警网违章查询小型汽车违章怎

2024年5月16日 19:53

电子音乐相册制作(怎样制作音乐相册上快手)

电子音乐相册制作(怎样制作音乐相册上快手)

其实电子音乐相册制作的问题并不复杂,但是又很多的朋友都不太了解怎样制作音乐相册上快手,因此呢,今天小编就来为大家分享电子音乐相册制作的一些知识,希望可以帮助到大家,下面我们一起来看看这个问题的分析吧!本文目录怎样制作音乐相册上快手微信朋友圈

2024年5月22日 05:14

长虹手机官网(长虹手机的虹是代表什么意思)

长虹手机官网(长虹手机的虹是代表什么意思)

本文目录长虹手机的虹是代表什么意思长虹虹手机多少钱长虹手机官网长虹手机的虹是代表什么意思虹phone的全名是——长虹智能手机虹phone。这款手机于4月10日正式在长虹手机官网宣布可以预订,而且现在预订的话,可享“长虹惠民价”1990元(市

2023年7月17日 07:40

召唤兽初值计算器(怎么算大话召唤兽的初值)

召唤兽初值计算器(怎么算大话召唤兽的初值)

本文目录怎么算大话召唤兽的初值大话2召唤兽计算器大话西游2中的召唤兽怎么查初值大话西游2现在召唤兽的初值计算器怎么不好用了呢感觉为什么没有大话2 当康召唤兽的计算器啊大话2原始敏和实际初敏怎么算大话2主页的召唤兽数据预测是不是错的,为什么现

2024年6月4日 19:35

球球大作战刷棒棒糖(球球大作战怎么刷棒棒糖 拿棒棒糖有什么用)

球球大作战刷棒棒糖(球球大作战怎么刷棒棒糖 拿棒棒糖有什么用)

本文目录球球大作战怎么刷棒棒糖 拿棒棒糖有什么用球球大作战刷棒棒糖方法攻略有哪些什么是刷棒棒糖球球大作战刷棒棒糖攻略 怎么一次性刷100个棒棒糖《球球大作战》刷10个棒棒糖的方法球球大作战怎么刷无限棒棒糖球球大作战怎么快速获得棒棒糖球球大作

2024年5月9日 17:05

近期文章

本站热文

iphone vpn设置(ios设置vpn快捷开关)
2024-07-22 15:01:12 浏览:2342
windows12正式版下载(操作系统Windows Server 2012 R2,在哪能下载到,公司用的)
2024-07-20 17:26:53 浏览:1736
client mfc application未响应(每次进cf就提示client MFC Application未响应该怎么办啊!急急急)
2024-07-20 11:15:58 浏览:1168
java安装教程(win10如何安装JAVA)
2024-07-19 19:55:49 浏览:1164
标签列表

热门搜索