精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

你不知道的Retrofit緩存庫RxCache

移動開發 Android
Retrofit無疑是當下最火的網絡請求庫,與同門師兄Okhttp配合使用,簡直是每個項目的標配,因為Okhttp自帶緩存,所以很多人并不關心其他緩存庫,但是使用過Okhttp緩存的小伙伴,肯定知道Okhttp的緩存必須配合Header使用,比較麻煩,也不夠靈活,所以現在為大家推薦一款專門為Retrifit打造的緩存庫RxCache.

前言

Retrofit無疑是當下最火的網絡請求庫,與同門師兄Okhttp配合使用,簡直是每個項目的標配,因為Okhttp自帶緩存,所以很多人并不關心其他緩存庫,但是使用過Okhttp緩存的小伙伴,肯定知道Okhttp的緩存必須配合Header使用,比較麻煩,也不夠靈活,所以現在為大家推薦一款專門為Retrifit打造的緩存庫RxCache.

項目地址: RxCache Demo地址: RxCacheSample

簡介

RxCache使用注解來為Retrofit配置緩存信息,內部使用動態代理和Dagger來實現,這個庫的資料相對較少,官方教程又是全英文的,這無疑給開發者增加了使用難度,其實我英文也不好,但是源碼是通用的啊,所以我為大家從源碼的角度來講解此庫,此庫源碼的難點其實都在Dagger注入上,我先為大家講解用法,后面會再寫篇文章講解源碼,在學習Dagger的朋友除了建議看看我的MVPArms外,還可以看看這個RxCache的源碼,能學到很多東西,先給張RxCache的架構圖,讓大家嘗嘗鮮,請期待我后面的源碼分析. 

RxCache的架構圖 

使用

1.定義接口,和Retrofit類似,接口中每個方法和Retrofit接口中的方法一一對應,每個方法的參數中必須傳入對應Retrofit接口方法的返回值(返回值必須為Observable,否則報錯),另外幾個參數DynamicKey,DynamicKeyGroup和EvictProvider不是必須的,但是如果要傳入,每個都只能傳入一個對象,否則報錯,這幾個參數的意義是初學者最困惑的,后面會分析.

  1. /** 
  2.  * 此為RxCache官方Demo 
  3.  */ 
  4. public interface CacheProviders { 
  5.  
  6.     @LifeCache(duration = 2, timeUnit = TimeUnit.MINUTES) 
  7.     Observable<Reply<List<Repo>>> getRepos(Observable<List<Repo>> oRepos, DynamicKey userName, EvictDynamicKey evictDynamicKey); 
  8.  
  9.     @LifeCache(duration = 2, timeUnit = TimeUnit.MINUTES) 
  10.     Observable<Reply<List<User>>> getUsers(Observable<List<User>> oUsers, DynamicKey idLastUserQueried, EvictProvider evictProvider); 
  11.  
  12.     Observable<Reply<User>> getCurrentUser(Observable<User> oUser, EvictProvider evictProvider); 
  13.  

2.將接口實例化,和Retrofit構建方式類似,將接口通過using方法傳入,返回一個接口的動態代理對象,調用此對象的方法傳入對應參數就可以實現緩存了,通過注解和傳入不同的參數可以實現一些自定義的配置, so easy~

  1. CacheProviders cacheProviders = new RxCache.Builder() 
  2.                 .persistence(cacheDir, new GsonSpeaker()) 
  3.                 .using(CacheProviders.class);  

詳解

其實RxCache的使用比較簡單,上面的兩步就可以輕松的實現緩存,此庫的的特色主要集中在對緩存的自定義配置,所以我來主要講講那些參數和注解是怎么回事?

參數

Observable

此Observable的意義為需要將你想緩存的Retrofit接口作為參數傳入(返回值必須為Observable),RxCache會在沒有緩存,或者緩存已經過期,或者EvictProvider為true時,通過這個Retrofit接口重新請求***的數據,并且將服務器返回的結果包裝成Reply返回,返回之前會向內存緩存和磁盤緩存中各保存一份.

值得一提的是,如果需要知道返回的結果是來自哪里(本地,內存還是網絡),是否加密,則可以使用Observable<Reply<List<Repo>>>作為方法的返回值,這樣RxCache則會使用Reply包裝結果,如果沒這個需求則直接在范型中聲明結果的數據類型Observable<List<Repo>>

例外

如果構建RxCache的時候將useExpiredDataIfLoaderNotAvailable設置成true,會在數據為空或者發生錯誤時,忽視EvictProvider為true或者緩存過期的情況,繼續使用緩存(前提是之前請求過有緩存).

DynamicKey & DynamicKeyGroup

有很多開發者最困惑的就是這兩個參數的意義,兩個一起傳以及不傳會有影響嗎?說到這里就要提下,RxCache是怎么存儲緩存的,RxCache并不是通過使用URL充當標識符來儲存和獲取緩存的.

那是什么呢?

沒錯RxCache就是通過這兩個對象加上上面CacheProviders接口中聲明的方法名,組合起來一個標識符,通過這個標識符來存儲和獲取緩存.

標識符規則為:

方法名 + $d$d$d$" + dynamicKey.dynamicKey + "$g$g$g$" + DynamicKeyGroup.group

dynamicKey或DynamicKeyGroup為空時則返回空字符串,即什么都不傳的標識符為:

"方法名$d$d$d$$g$g$g$"

什么意思呢?

比如RxCache,的內存緩存使用的是Map,它就用這個標識符作為Key,put和get數據(本地緩存則是將這個標識符作為文件名,使用流寫入或讀取這個文件,來儲存或獲取緩存),如果儲存和獲取的標識符不一致那就取不到想取的緩存.

和我們有什么關系呢?

舉個例子,我們一個接口具有分頁功能,我們使用RxCache給他設置了3分鐘的緩存,如果這兩個對象都不傳入參數中,它會默認使用這個接口的方法名去存儲和獲取緩存,意思是我們之前使用這個接口獲取到了***頁的數據,三分鐘以內多次調用這個接口,請求其他分頁的數據,它返回的緩存還是***頁的數據,直到緩存過期,所以我們現在想具備分頁功能,必須傳入DynamicKey,DynamicKey內部存儲有一個key,我們在構建的時候傳入頁數,RxCache將會根據不同的頁數分別保存一份緩存,它內部做的事就是將方法名+DynamicKey變成一個String類型的標識符去獲取和存儲緩存.

DynamicKey和DynamicKeyGroup有什么關系呢?

DynamicKey存儲有一個Key,DynamicKey的應用場景: 請求同一個接口,需要參照一個變量的不同返回不同的數據,比如分頁,構造時傳入頁數就可以了.

DynamicKeyGroup存儲有兩個key,DynamicKeyGroup是在DynamicKey基礎上的加強版,應用場景:請求同一個接口不僅需要分頁,每頁又需要根據不同的登錄人返回不同的數據,這時候構造DynamicKeyGroup時,在構造函數中***個參數傳頁數,第二個參數傳用戶標識符就可以了.

理論上DynamicKey和DynamicKeyGroup根據不同的需求只用傳入其中一個即可,但是也可以兩個參數都傳,以上面的需求為例,兩個參數都傳的話,它會先取DynamicKey的Key(頁數)然后再取DynamicKeyGroup的第二個Key(用戶標識符),加上接口名組成標識符,來獲取和存儲數據,這樣就會忽略DynamicKeyGroup的***個Key(頁數).

EvictProvider & EvictDynamicKey & EvictDynamicKeyGroup

這三個對象內部都保存有一個boolean類型的字段,其意思為是否驅逐(使用或刪除)緩存,RxCache在取到未過期的緩存時,會根據這個boolean字段,考慮是否使用這個緩存,如果為true,就會重新通過Retrofit獲取新的數據,如果為false就會使用這個緩存.

這三個對象有什么關系呢?

這三個對象是相互繼承關系,繼承關系為EvictProvider < EvictDynamicKey < EvictDynamicKeyGroup,這三個對象你只能傳其中的一個,多傳一個都會報錯,按理說你不管傳那個對象都一樣,因為里面都保存有一個boolean字段,根據這個字段判斷是否使用緩存.

不同在哪呢?

如果有未過期的緩存,并且里面的boolean為false時,你傳這三個中的哪一個都是一樣的,但是在boolean為true時,這時就有區別了,RxCache會在Retrofit請求到新數據后,在boolean為true時刪除對應的緩存.

刪除規則是什么呢?

還是以請求一個接口,該接口的數據會根據不同的分頁返回不同的數據,并且同一個分頁還要根據不同用戶顯示不同的數據為例

三個都不傳,RxCache會自己new EvictProvider(false);,這樣默認為false就不會刪除任何緩存

EvictDynamicKeyGroup 只會刪除對應分頁下,對應用戶的緩存.

EvictDynamicKey 會刪除那個分頁下的所有緩存,比如你請求的是***頁下user1的數據,它不僅會刪除user1的數據還會刪除當前分頁下其他user2,user3...的數據.

EvictProvider 會刪除當前接口下的所有緩存,比如你請求的是***頁的數據,它不僅會刪除***頁的數據,還會把這個接口下其他分頁的數據全刪除.

所以你可以根據自己的邏輯選擇傳那個對象,如果請求的這個接口沒有分頁功能,這時你不想使用緩存,按理說你應該傳EvictProvider,并且在構造時傳入true,但是你如果傳EvictDynamicKey和EvictDynamicKeyGroup達到的效果也是一樣.

注解

@LifeCache

@LifeCache顧名思義,則是用來定義緩存的生命周期,當Retrofit獲取到***的數據時,會將數據及數據的配置信息封裝成Record,在本地和內存中各保存一份,Record中則保存了@LifeCache的值(毫秒)和當前數據請求成功的時間(毫秒)timeAtWhichWasPersisted.

以后每次取緩存時,都會判斷timeAtWhichWasPersisted+@LifeCache的值是否小于當前時間(毫秒),小于則過期,則會立即清理當前緩存,并使用Retrofit重新請求***的數據,如果EvictProvider為true不管緩存是否過期都不會使用緩存.

@EncryptKey & @Encrypt

這兩個注解的作用都是用來給緩存加密,區別在于作用域不一樣

@EncryptKey是作用在接口上

  1. @EncryptKey("123")public interface CacheProviders { 
  2.  
  3.  

而@Encrypt是作用在方法上

  1. @EncryptKey("123")public interface CacheProviders {    @Encrypt 
  2.    Observable<Reply<User>> getCurrentUser(Observable<User> oUser, EvictProvider evictProvider); 
  3.  

如果需要給某個接口的緩存做加密的操作,則在對應的方法上加上@Encrypt,在存儲和獲取緩存時,RxCache就會使用@EncryptKey的值作為Key給緩存數據進行加解密,因此每個Interface中的所有的方法都只能使用相同的Key.

值得注意的時,RxCache只會給本地緩存進行加密操作,并不會給內存緩存進行加密,給本地數據加密使用的是Java自帶的CipherInputStream,解密使用的是CipherOutputStream

@Expirable

還記得我們在構建RxCache時,有一個setMaxMBPersistenceCache方法,這個可以設置,本地緩存的***容量,單位為MB,如果沒設置則默認為100MB.

這個***容量和@Expirable又有什么關系呢?

當然有!還記得我之前說過在每次Retrofit重新獲取***數據時,返回數據前會將***數據在內存緩存和本地緩存中各存一份.

存儲完畢后,會檢查現在的本地緩存大小,如果現在本地緩存中存儲的所有緩存大小加起來大于或者等于setMaxMBPersistenceCache中設置的大小(默認為100MB)的百分之95,RxCache就會做一些操作,將總的緩存大小控制在百分之70以下.

做的什么操作?

很簡單,RxCache會遍歷,構建RxCache時傳入的cacheDirectory中的所有緩存數據,一個個刪除直到總大小小于百分70,遍歷的順序不能保證,所以搞不好對你特別重要的緩存就被刪除了,這時@Expirable就派上用場了,在方法上使用它并且給它設置為false(如果沒使用這個注解,則默認為true),就可以保證這個接口的緩存數據,在每次需要清理時都幸免于難.

  1. @Expirable(false
  2.    Observable<Reply<User>> getCurrentUser(Observable<User> oUser, EvictProvider evictProvider);  

值得注意的是: 構建RxCache時persistence方法傳入的cacheDirectory,是用來存放RxCache本地緩存的文件夾,這個文件夾里***不要有除RxCache之外的任何數據,這樣會在每次需要遍歷清理緩存時,節省不必要的開銷,因為RxCache并沒檢查文件名,不管是不是自己的緩存,他都會去遍歷獲取

@SchemeMigration & @Migration

這兩個注解是用來數據遷移的,用法:

  1. @SchemeMigration({ 
  2.             @Migration(version = 1, evictClasses = {Mock.class}), 
  3.             @Migration(version = 2, evictClasses = {Mock2.class}) 
  4.     }) 
  5. interface Providers {}  

什么叫數據遷移呢?

簡單的說就是在***的版本中某個接口返回值類型內部發生了改變,從而獲取數據的方式發生了改變,但是存儲在本地的數據,是未改變的版本,這樣在反序列化時就可能發生錯誤,為了規避這個風險,作者就加入了數據遷移的功能.

有什么應用場景呢?

可能上面的話,不是很好理解,舉個非常簡單的例子:

  1. public class Mock{ 
  2.     private int id; 
  3.  

Mock里面有一個字段id,現在是一個整型int,能滿足我們現在的需求,但是隨著產品的迭代,發現int不夠用了

  1. public class Mock{ 
  2.     private long id; 
  3.  

為了滿足現在的需求,我們使用long代替int,由于緩存中的Mock還是之前未改變的版本,并且未過期,在使用本地緩存時會將數據反序列化,將int變為long,就會出現問題.

數據遷移是怎么解決上面的問題呢?

其實非常簡單,就是使用注解聲明,之前有緩存并且內部修改過的class,RxCache會把含有這些class的緩存全部清除掉.

RxCache是怎么操作的呢?

值得一提的是,在每次創建接口的動態代理時,也就是在每次調用RxCache.using(CacheProviders.class)時,會執行兩個操作,清理含有@Migration中聲明的evictClasses的緩存,以及遍歷本地緩存文件夾清理所有已經過期的緩存.

每次清理完需要數據遷移的緩存時,會將version值***的@Migration的version值保存到本地.

  1. @SchemeMigration({ 
  2.             @Migration(version = 1, evictClasses = {Mock.class}), 
  3.             @Migration(version = 3, evictClasses = {Mock3.class}), 
  4.             @Migration(version = 2, evictClasses = {Mock2.class}) 
  5.     }) 
  6. interface Providers {}  

如上面的聲明方式,它會將3保存到本地,每次調用using(),開始數據遷移時會將上次保存的version值從本地取出來,會在@SchemeMigration中查找大于這個version值的@Migration,取出里面evictClasses,去重后,遍歷所有本地緩存,只要緩存數據中含有你聲明的class,就將這個緩存清除.

比如evictClasses中聲明了Mock.class,會把以Observable< List< Mock >>,Observable< Map< String,Mock > >,Observable < Mock[] >或者Observable< Mock >作為返回值的接口緩存全部清理掉,然后在將***version值記錄到本地.

所以每次有需要數據遷移的類時,必須在@SchemeMigration中添加新的@Migration,并且注解中version的值必須+1,這樣才會達到數據遷移的效果.

  1. @SchemeMigration({ 
  2.             @Migration(version = 1, evictClasses = {Mock.class}), 
  3.             @Migration(version = 3, evictClasses = {Mock3.class}), 
  4.             @Migration(version = 2, evictClasses = {Mock2.class}), 
  5.             @Migration(version = 4, evictClasses = {Mock2.class}) 
  6.  
  7.     }) 
  8. interface Providers {}  

如在上面的基礎上,Mock2內部又發生改變,又需要數據遷移,就要新添加個@Migration,version = 4(3+1),這時在調用using()時只會將version = 4的@Migration中evictClasses聲明的class進行數據遷移(即清理含有這個class的緩存數據).

@Actionable

這個注解在官方介紹中說明了會使用注解處理器給使用了這個注解的Interface,自動生成一個相同類名以Actionable結尾的類文件,使用這個類的APi方便更好的執行寫操作,沒使用過,不做過多介紹.

總結

到這里RxCache的介紹就告一段落了,相信看完這篇文章后,基本使用肯定是沒問題的

但是在使用中發現了一個問題,如果使用BaseResponse< T >,包裹數據的時候會出現錯誤,如issue#41和issue#73.

分析問題

上面說了RxCache會將Retrofit返回的數據封裝到Record對象里,Record會判斷這個數據是那種類型,會先判斷這個數據是否是Collection(List的父類),數組還是Map,如果都不是他會默認這個數據就是普通的對象.

Record里有三個字段分別儲存這個數據的,容器類名,容器里值的類名,和Map的Key類名,意思為如果數據類型為List< String >,容器類名為List,值類名為String,Key類名為空,如果數據類型為Map< String,Integer >,容器類名為Map,值類名為Integer,key類名為String.

這三個字段的作用就是,在取本地緩存時可以使用Gson根據字段類型恢復真實數據的類型,問題就在這,因為使用的是BaseResponse< T >包裹數據,在上面的判斷里,他排除了這個數據是List,數組或Map后它只會認定這個數據是普通的對象,這時他只會把三個字段里中值類名保存為BaseResponse其他則為空,范型的類型它并沒通過字段記錄,所以它在取的時候自然不會正確返回T的類型.

解決問題

知道問題所在后,我們現在就來解決問題,解決這個問題現在有兩個方向,一個是內部解決,一個是外部解決,外部解決的方式就可以通過上面issue#73所提到的方式.

所謂內部解決就要改這個框架的內部代碼了,問題就出在Record在數據為普通對象的時候,他不會使用字段保存范型的類型名,所以在取本地緩存的時候就無法正確恢復數據類型

解決的思路就是我們必須對數據為普通對象的時候做特殊處理,最簡單的方式就是如果數據為對象時我們再判斷instanceof BaseResponse,如果為true我們就重復做上面的判斷.

即判斷BaseResponse中,T的類型是否為List,數組,Map還是對象?

然后在用對應的字段保存對應的類型名,取本地緩存的時候就可以用Gson按這些字段恢復正確的數據類型,但是這樣強制的判斷instanceof對于一個框架來說靈活性和擴展性會大打折扣,所以我后面寫源碼分析的時候會認真考慮下這個問題,可以的話我會Pull Request給Rxcache. 

責任編輯:龐桂玉 來源: 安卓巴士Android開發者門戶
相關推薦

2020-06-12 09:20:33

前端Blob字符串

2020-07-28 08:26:34

WebSocket瀏覽器

2009-12-10 09:37:43

2022-10-13 11:48:37

Web共享機制操作系統

2021-02-01 23:23:39

FiddlerCharlesWeb

2011-09-15 17:10:41

2010-08-23 09:56:09

Java性能監控

2020-12-21 09:00:04

MySQL緩存SQL

2022-11-04 08:19:18

gRPC框架項目

2020-09-15 08:35:57

TypeScript JavaScript類型

2021-10-17 13:10:56

函數TypeScript泛型

2012-11-23 10:57:44

Shell

2021-12-29 11:38:59

JS前端沙箱

2021-12-22 09:08:39

JSON.stringJavaScript字符串

2015-06-19 13:54:49

2020-08-11 11:20:49

Linux命令使用技巧

2020-12-21 09:44:53

MySQL查詢緩存數據庫

2014-03-12 09:23:06

DevOps團隊合作

2012-06-26 15:49:05

2023-12-21 14:40:09

Python編程語言
點贊
收藏

51CTO技術棧公眾號

青草热久免费精品视频| 欧美人xxxx| 精品一卡二卡三卡四卡日本乱码 | 国产精品入口免费视| 永久免费看片视频教学| 国产精品麻豆| 精品久久久久久久久中文字幕| 日韩精品一线二线三线| 99久久精品国产成人一区二区| 黄色精品免费| 亚洲男女性事视频| 一级片黄色免费| 国产精品蜜芽在线观看| 国产精品私人自拍| 国产一区二区久久久| 91精品国产色综合久久不8| 韩国av一区| 中文字幕欧美国内| 亚洲一区二区三区黄色| 激情久久一区二区| 午夜av一区二区| 一区二区三区在线视频111| 天天操天天干天天插| 精品一区中文字幕| 欧美怡红院视频一区二区三区| 日韩成人毛片视频| 欧美一区二区三区高清视频| 亚洲国产精品国自产拍av秋霞| 色啦啦av综合| 春暖花开亚洲一区二区三区| 亚洲国产日产av| 在线观看成人av电影| 同心难改在线观看| 成人一区二区三区中文字幕| 亚洲成av人片一区二区| x99av成人免费| 少妇户外露出[11p]| 国产日韩一区二区三免费高清| 欧洲一区二区三区在线| 国产精品秘入口18禁麻豆免会员| caopeng在线| 国产精品国产精品国产专区不蜜 | 精品一区二区三区中文字幕老牛| 亚洲精品福利免费在线观看| www.555国产精品免费| 国产一区二区久久久久| 欧美日韩国产高清一区二区| www.xxx亚洲| 91九色在线播放| 亚洲二区在线观看| 99久久久精品视频| 尤物视频在线看| 亚洲激情六月丁香| 日本一区二区三区四区五区六区| 欧美a在线看| 亚洲丝袜自拍清纯另类| 在线免费观看成人网| av电影在线网| 亚洲欧洲美洲综合色网| 26uuu成人| av香蕉成人| 一区二区欧美精品| 国产一区 在线播放| 国产啊啊啊视频在线观看| 亚洲高清在线视频| 日本xxxxxxxxxx75| jizz一区二区三区| 亚洲一区二区三区三| 日韩亚洲欧美视频| 欧美极品少妇videossex| 亚洲第一av色| 国产91在线视频观看| 桃花岛成人影院| 欧美性生活影院| 国产成人在线综合| 亚洲成人影音| 精品伊人久久97| 欧美亚洲色综久久精品国产| 天天在线视频色| 亚洲日本三级| 日韩女优制服丝袜电影| 亚洲成av人片在线观看无| 欧美午夜18电影| 久久精品人妻一区二区三区| 天堂在线中文网官网| 欧美日韩亚洲精品内裤| 亚洲天堂av线| 免费观看性欧美大片无片| 亚洲国产另类 国产精品国产免费| 亚洲一区二区三区无码久久| 精品国产一区探花在线观看 | 岛国视频一区| 激情小视频在线观看| 亚洲欧美自拍偷拍色图| www.国产在线视频| 三级成人在线| 欧美一区二区三区爱爱| 动漫精品一区二区三区| 性欧美69xoxoxoxo| 欧美一级淫片丝袜脚交| 97精品人妻一区二区三区在线 | 视频一区视频二区视频三区视频四区国产 | 国产一区二区三区成人| jizz一区二区| 正义之心1992免费观看全集完整版| 国产后进白嫩翘臀在线观看视频 | 欧美自拍视频在线| 一本色道久久综合亚洲| 91视频在线看| 黄色片免费在线观看视频| 欧美动物xxx| 日韩女同互慰一区二区| 日韩视频在线观看免费视频| 极品中文字幕一区| 国产日韩中文在线| 久久精品国产综合精品| 亚洲风情第一页| 国产精品天天摸av网| 国产妇女馒头高清泬20p多| 国产亚洲精彩久久| 日韩精品中文在线观看| 欧美黑人一级片| 免费成人你懂的| 久久久久国产精品视频| 欧美xxxx视频| 欧美日韩国产高清一区二区三区 | 亚洲 精品 综合 精品 自拍| 亚洲毛片av在线| 亚洲第一狼人区| 红杏视频成人| 欧美成人黄色小视频| 中文字幕乱码一区二区| 91久色porny| 激情五月宗合网| 91精品尤物| 欧美大片va欧美在线播放| 91女人18毛片水多国产| 国产女人aaa级久久久级| 9久久9毛片又大又硬又粗| 懂色av一区二区| 欧美黑人xxx| 国产成人毛毛毛片| 亚洲女同女同女同女同女同69| 91热这里只有精品| 超碰成人久久| 国产精品你懂得| 91女主播在线观看| 欧美午夜影院一区| 精品亚洲aⅴ无码一区二区三区| 亚洲资源av| 欧美日韩国产三区| 国模套图日韩精品一区二区| 亚洲免费小视频| 成年人视频免费| 欧美激情在线一区二区三区| 最新天堂中文在线| 91青青国产在线观看精品| 国产欧美一区二区三区在线看 | 三日本三级少妇三级99| 国产精品50页| 在线免费观看日本欧美爱情大片| 91久久精品视频| 羞羞视频在线观看免费| 日韩欧美亚洲国产另类| 动漫精品一区一码二码三码四码| av欧美精品.com| 激情网站五月天| 日韩视频在线观看| 92国产精品视频| 女囚岛在线观看| 亚洲精品久久久久久久久久久久 | 欧美高清视频www夜色资源网| 我要看一级黄色录像| 国产一区二区不卡老阿姨| 亚洲啊啊啊啊啊| 日韩mv欧美mv国产网站| 国产精品久久91| 二区三区在线观看| 日韩欧美国产高清| 看片网址国产福利av中文字幕| 国产亚洲一区二区三区| 国产精品自在自线| 狠狠入ady亚洲精品经典电影| 国产一区二区三区奇米久涩| 国产成人精品一区二区三区免费| 欧美精品生活片| 男同在线观看| 欧美一区中文字幕| 国产小视频在线免费观看| 欧美国产一区二区在线观看 | 日本一区二区三区电影免费观看| 亚洲**2019国产| 在线观看黄av| 亚洲第一页中文字幕| 久久人人爽人人爽人人片av免费| 亚洲美女视频一区| 男女黄床上色视频| 国产美女精品人人做人人爽| 波多野结衣家庭教师视频| 91精品国产乱码久久久久久久| 激情伦成人综合小说| 亚洲精品伊人| 日本精品久久久久久久| 在线观看中文| 在线不卡国产精品| 色wwwwww| 欧美一级在线视频| 婷婷激情五月综合| 亚洲一二三四久久| 天堂网中文在线观看| 99久久777色| 久久精品福利视频| a天堂在线视频| 欧美性受极品xxxx喷水| 日韩一区二区视频在线| 一二三区精品福利视频| 精品丰满少妇一区二区三区| av一本久道久久综合久久鬼色| 天天看片天天操| 久久精品国语| 欧美 日韩 亚洲 一区| 亚洲老妇激情| 亚洲一二三区精品| 国产精品亚洲人成在99www| 国产精品久久亚洲| 国产亚洲高清在线观看| 国产精品国产三级国产aⅴ9色 | 国产精品狠色婷| 涩涩在线视频| 97香蕉久久夜色精品国产| caopeng在线| 久久国产精品免费视频| 五月婷婷在线观看| 最新国产成人av网站网址麻豆| 免费资源在线观看| 亚洲精品久久久久久久久久久| 人妻无码中文字幕| 91精品国产综合久久福利| 在线观看黄色国产| 欧美日韩一区二区三区不卡| 91丨九色丨海角社区| 色婷婷久久久亚洲一区二区三区 | 精品999久久久| 亚洲国产成人在线观看| 日韩亚洲电影在线| 国产丰满果冻videossex| 91精品啪在线观看国产60岁| 一区二区三区日| 欧美精品日韩精品| 国产乱淫片视频| 欧美一级黄色录像| 亚洲国产www| 亚洲国产97在线精品一区| 色窝窝无码一区二区三区成人网站| 亚洲福利在线播放| 日本一卡二卡四卡精品| 国产亚洲精品久久久优势| 国产三级电影在线观看| 日韩在线免费视频| 国产三区在线观看| 欧美日韩爱爱视频| free性欧美| 欧美一区二区.| 欧美福利在线播放| 成人黄色免费片| 日韩精品一区二区三区中文字幕 | 日本精品国产| 久久精品国产亚洲7777| 2024最新电影在线免费观看| 欧美第一页在线| 欧美男男激情videos| 国产精品美女久久久久久免费| 成人自拍视频| 国产视频99| 精品免费在线| 日韩精品一区二区三区电影| 日韩视频三区| 538在线视频观看| 国产在线播放一区| 亚洲天堂2024| 中文天堂在线一区| 久久久精品国产sm调教| 色丁香久综合在线久综合在线观看| 一区不卡在线观看| 精品国产污网站| 黄视频在线播放| 久久69精品久久久久久国产越南| 超碰99在线| 国产欧美va欧美va香蕉在线| 亚洲1区在线观看| 欧美在线视频二区| 午夜天堂精品久久久久| 日韩网址在线观看| 精品在线播放午夜| 欧美老熟妇乱大交xxxxx| 亚洲欧美日韩国产综合在线 | 羞羞的视频在线观看| 4438全国亚洲精品在线观看视频| 欧美a一级片| 久久99精品久久久久久水蜜桃| 99tv成人| 成人一级片网站| 国产99久久久精品| 手机看片福利视频| 亚洲大尺度视频在线观看| 中文字幕视频在线播放| 亚洲第一区中文99精品| 日本三级在线视频| 日本一区二区三区在线播放| 日本免费精品| 中文字幕一区二区三区最新| 久久高清一区| 动漫美女无遮挡免费| 椎名由奈av一区二区三区| www.色国产| 亚洲精品成人久久电影| 91在线中文| 成人两性免费视频| 国内精品久久久久久久影视简单| 国产69精品久久久久999小说| 国产呦萝稀缺另类资源| 懂色av粉嫩av浪潮av| 日韩欧美国产网站| 女人18毛片一区二区三区| 久久成人在线视频| 日韩成人免费av| 视频一区视频二区视频| 日韩成人一区二区三区在线观看| 亚洲精品中文字幕在线播放| 亚洲一区在线观看免费 | 日本熟妇毛茸茸丰满| 亚洲成人av在线电影| 精品国产伦一区二区三| 久久精品国产96久久久香蕉| 久久精品97| 亚洲精品成人a8198a| 视频一区二区中文字幕| 人妻精品久久久久中文字幕 | 亚洲精品乱码久久久久久自慰| 不卡的av网站| 日本少妇裸体做爰| 精品国产sm最大网站| 欧美巨大xxxx做受沙滩| 国产激情一区二区三区在线观看| 中文字幕一区二区av | 亚洲免费一区三区| 久久久国内精品| 国产成a人亚洲| xxxx 国产| 日韩高清人体午夜| 欧美成人h版| 日韩av影视| 麻豆视频观看网址久久| 女人18毛片毛片毛片毛片区二| 91麻豆精品国产无毒不卡在线观看| 免费av网站在线观看| 亚洲综合精品一区二区| 欧美日本中文| 中国黄色片视频| 色综合色综合色综合| 国产经典自拍视频在线观看| 国产日本欧美一区二区三区| 你懂的网址国产 欧美| 91传媒理伦片在线观看| 欧美日韩亚洲一区二| jizz在线观看视频| 国产欧美一区二区三区久久人妖| 91精品电影| 亚洲午夜久久久久久久久| 狠狠做深爱婷婷久久综合一区 | 欧美精品久久久久久久| 香蕉一区二区| 亚洲欧美视频二区| 亚洲资源在线观看| 国产小视频免费在线观看| 国产精品亚洲片夜色在线| 欧美日韩亚洲一区三区| 精品人妻少妇嫩草av无码| 欧美日韩精品福利| 波多野结衣在线高清| 欧美污视频久久久| 国产原创一区二区| 亚洲精品中文字幕乱码三区91| 视频在线观看一区二区| 国产精品tv| 一区二区xxx| 亚洲国产成人91porn| 91在线网址| 懂色一区二区三区av片| 日韩和欧美的一区| 久草视频在线资源| 亚洲人午夜色婷婷| 亚洲高清在线一区| 国产激情在线观看视频| 一区二区三区日韩欧美精品| 九色视频在线观看免费播放 | 中文字幕日韩综合| 午夜精品久久久久久久久| 午夜看片在线免费| 一区二区三区国产在线观看|