日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

一款基于RxJava2+Retrofit2实现简单易用的网络请求框架

發布時間:2025/3/19 java 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一款基于RxJava2+Retrofit2实现简单易用的网络请求框架 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本庫是一款基于RxJava2+Retrofit2實現簡單易用的網絡請求框架,結合android平臺特性的網絡封裝庫,采用api鏈式調用一點到底,集成cookie管理,多種緩存模式,極簡https配置,上傳下載進度顯示,請求錯誤自動重試,請求攜帶token、時間戳、簽名sign動態配置,自動登錄成功后請求重發功能,3種層次的參數設置默認全局局部,默認標準ApiResult同時可以支持自定義的數據結構,已經能滿足現在的大部分網絡請求。
注:Retrofit和Rxjava是當下非常火爆的開源框架,均來自神一般的公司。本庫就不介紹Retrofit和Rxjava2的用法。

為什么會封裝此庫?

網上好的開源網絡庫像Volley、async-http、okhttp、retrofit等都非常強大,但是實際應用中我們不會直接去使用,一般都會根據自己的業務再封裝一層,這樣更方便快捷,又能統一處理業務共性的東西例如:統一的數據結構(code、msg、data)、token處理、網絡異常等情況。在使用retrofit來請求網絡的時候,項目的需求越來越多,api也隨之越來越多,一個普通的應用api一般也在100+左右。如果把這些api放在一個ApiService內會很臃腫,不利于查看api.如果采用模塊的方式對api進行分類,每個模塊對應若干個api.以retrofit的使用方式又需要創建若干個ApiService,這種方式維護方便,但是模塊增多了,類也增多了很多。對于懶人來說就想通過一個URL就能回調你所需要的數據,什么ApiService都不想理會,同時又可以很快的與自己的業務相關聯,就類似于代替你在開源網絡庫基礎上再封裝一層的作用,于是本庫就應運而生。

特點

?比Retrofit使用更簡單、更易用。

?采用鏈式調用一點到底

?加入基礎ApiService,減少Api冗余

?支持動態配置和自定義底層框架Okhttpclient、Retrofit.

?支持多種方式訪問網絡GET、POST、PUT、DELETE等請求協議

?支持網絡緩存,八種緩存策略可選,涵蓋大多數業務場景

?支持固定添加header和動態添加header

?支持添加全局參數和動態添加局部參數

?支持文件下載、多文件上傳和表單提交數據

?支持文件請求、上傳、下載的進度回調、錯誤回調,也可以自定義回調

?支持默認、全局、局部三個層次的配置功能

?支持任意數據結構的自動解析

?支持添加動態參數例如timeStamp時間戳、token、簽名sign

?支持自定義的擴展API

?支持多個請求合并

?支持Cookie管理

?支持異步、同步請求

?支持Https、自簽名網站Https的訪問、雙向驗證

?支持失敗重試機制,可以指定重試次數、重試間隔時間

?支持根據ky刪除網絡緩存和清空網絡緩存

?提供默認的標準ApiResult解析和回調,并且可自定義ApiResult

?支持取消數據請求,取消訂閱,帶有對話框的請求不需要手動取消請求,對話框消失會自動取消請求

?支持請求數據結果采用回調和訂閱兩種方式

?api設計上結合http協議和android平臺特點來實現,loading對話框,實時進度條顯示

?返回結果和異常統一處理

?結合RxJava2,線程智能控制

演示(請star支持)

RxEasyHttp與Rxjava結合使用場景演示

build.gradle設置
dependencies {
compile 'com.zhouyou:rxeasyhttp:2.0.8'
}

權限說明

如果使用本庫實現文件下載到SD卡、或者配置了緩存數據到SD卡,你必須要考慮到Android6.0及以上系統的運行時權限,給大家推薦兩個權限庫:

AndPermission
RxPermissions

因為要請求網絡、從SD卡讀寫緩存、下載文件到SD卡等等,所以需要在manifest.xml中配置以下幾個權限,如果你已經配置過了這些權限,請不要重復配置:



全局配置

一般在 Aplication,或者基類中,只需要調用一次即可,可以配置調試開關,全局的超時時間,公共的請求頭和請求參數等信息
初始化需要一個Context,最好在Application#onCreate()中初始化,記得在manifest.xml中注冊Application。

Application:
public class MyApplication extends Application {

@Override public void onCreate() {super.onCreate(); }

}

manifest.xml:
...

android:name=".MyApplication" ...

/>

默認初始化

如果使用默認始化后,一切采用默認設置。如果你需要配置全局超時時間、緩存、Cookie、底層為OkHttp的話,請看高級初始化。
public class MyApplication extends Application {

@Override public void onCreate() {super.onCreate();EasyHttp.init(this);//默認初始化 }

}

高級初始化

可以進行超時配置、網絡緩存配置、okhttp相關參數配置、retrofit相關參數配置、cookie配置等,這些參數可以選擇性的根據業務需要配置。
public class MyApplication extends Application {

@Override public void onCreate() {super.onCreate();EasyHttp.init(this);//默認初始化,必須調用//全局設置請求頭HttpHeaders headers = new HttpHeaders();headers.put("User-Agent", SystemInfoUtils.getUserAgent(this, AppConstant.APPID));//全局設置請求參數HttpParams params = new HttpParams();params.put("appId", AppConstant.APPID);//以下設置的所有參數是全局參數,同樣的參數可以在請求的時候再設置一遍,那么對于該請求來講,請求中的參數會覆蓋全局參數EasyHttp.getInstance()//可以全局統一設置全局URL.setBaseUrl(Url)//設置全局URL url只能是域名 或者域名+端口號 // 打開該調試開關并設置TAG,不需要就不要加入該行// 最后的true表示是否打印內部異常,一般打開方便調試錯誤.debug("EasyHttp", true)//如果使用默認的60秒,以下三行也不需要設置.setReadTimeOut(60 * 1000).setWriteTimeOut(60 * 100).setConnectTimeout(60 * 100)//可以全局統一設置超時重連次數,默認為3次,那么最差的情況會請求4次(一次原始請求,三次重連請求),//不需要可以設置為0.setRetryCount(3)//網絡不好自動重試3次//可以全局統一設置超時重試間隔時間,默認為500ms,不需要可以設置為0.setRetryDelay(500)//每次延時500ms重試//可以全局統一設置超時重試間隔疊加時間,默認為0ms不疊加.setRetryIncreaseDelay(500)//每次延時疊加500ms//可以全局統一設置緩存模式,默認是不使用緩存,可以不傳,具體請看CacheMode.setCacheMode(CacheMode.NO_CACHE)//可以全局統一設置緩存時間,默認永不過期.setCacheTime(-1)//-1表示永久緩存,單位:秒 ,Okhttp和自定義RxCache緩存都起作用//全局設置自定義緩存保存轉換器,主要針對自定義RxCache緩存.setCacheDiskConverter(new SerializableDiskConverter())//默認緩存使用序列化轉化//全局設置自定義緩存大小,默認50M.setCacheMaxSize(100 * 1024 * 1024)//設置緩存大小為100M//設置緩存版本,如果緩存有變化,修改版本后,緩存就不會被加載。特別是用于版本重大升級時緩存不能使用的情況.setCacheVersion(1)//緩存版本為1//.setHttpCache(new Cache())//設置Okhttp緩存,在緩存模式為DEFAULT才起作用//可以設置https的證書,以下幾種方案根據需要自己設置.setCertificates() //方法一:信任所有證書,不安全有風險//.setCertificates(new SafeTrustManager()) //方法二:自定義信任規則,校驗服務端證書//配置https的域名匹配規則,不需要就不要加入,使用不當會導致https握手失敗//.setHostnameVerifier(new SafeHostnameVerifier())//.addConverterFactory(GsonConverterFactory.create(gson))//本框架沒有采用Retrofit的Gson轉化,所以不用配置.addCommonHeaders(headers)//設置全局公共頭.addCommonParams(params)//設置全局公共參數//.addNetworkInterceptor(new NoCacheInterceptor())//設置網絡攔截器//.setCallFactory()//局設置Retrofit對象Factory//.setCookieStore()//設置cookie//.setOkproxy()//設置全局代理//.setOkconnectionPool()//設置請求連接池//.setCallbackExecutor()//全局設置Retrofit callbackExecutor//可以添加全局攔截器,不需要就不要加入,錯誤寫法直接導致任何回調不執行//.addInterceptor(new GzipRequestInterceptor())//開啟post數據進行gzip后發送給服務器.addInterceptor(new CustomSignInterceptor());//添加參數簽名攔截器 }

}

請求數據

網絡請求,采用鏈式調用,支持一點到底。

入口方法
/**

* get請求*/ public static GetRequest get(String url);/*** post請求和文件上傳*/ public static PostRequest post(String url);/*** delete請求*/ public static DeleteRequest delete(String url) ;/*** 自定義請求*/ public static CustomRequest custom();/*** 文件下載*/ public static DownloadRequest downLoad(String url) ;/*** put請求*/ public static PutRequest put(String url);

通用功能配置

1.包含一次普通請求所有能配置的參數,真實使用時不需要配置這么多,按自己的需要選擇性的使用即可

2.以下配置全部是單次請求配置,不會影響全局配置,沒有配置的仍然是使用全局參數。

3.為單個請求設置超時,比如涉及到文件的需要設置讀寫等待時間多一點。

完整參數GET示例:
EasyHttp.get("/v1/app/chairdressing/skinAnalyzePower/skinTestResult")

.baseUrl("http://www.xxxx.com")//設置url.writeTimeOut(30*1000)//局部寫超時30s,單位毫秒.readTimeOut(30*1000)//局部讀超時30s,單位毫秒.connectTimeout(30*1000)//局部連接超時30s,單位毫秒.headers(new HttpHeaders("header1","header1Value"))//添加請求頭參數.headers("header2","header2Value")//支持添加多個請求頭同時添加.headers("header3","header3Value")//支持添加多個請求頭同時添加.params("param1","param1Value")//支持添加多個參數同時添加.params("param2","param2Value")//支持添加多個參數同時添加//.addCookie(new CookieManger(this).addCookies())//支持添加Cookie.cacheTime(300)//緩存300s 單位s.cacheKey("cachekey")//緩存key.cacheMode(CacheMode.CACHEANDREMOTE)//設置請求緩存模式//.okCache()//使用模式緩存模式時,走Okhttp緩存.cacheDiskConverter(new GsonDiskConverter())//GSON-數據轉換器//.certificates()添加證書.retryCount(5)//本次請求重試次數.retryDelay(500)//本次請求重試延遲時間500ms.addInterceptor(Interceptor)//添加攔截器.okproxy()//設置代理.removeHeader("header2")//移除頭部header2.removeAllHeaders()//移除全部請求頭.removeParam("param1").accessToken(true)//本次請求是否追加token.timeStamp(false)//本次請求是否攜帶時間戳.sign(false)//本次請求是否需要簽名.syncRequest(true)//是否是同步請求,默認異步請求。true:同步請求.execute(new CallBack<SkinTestResult>() {@Overridepublic void onStart() {//開始請求}@Overridepublic void onCompleted() {//請求完成}@Overridepublic void onError(ApiException e) {//請求錯誤}@Overridepublic void onSuccess(SkinTestResult response) {//請求成功}});

url

Url可以通過初始化配置的時候傳入EasyHttp.getInstance().setBaseUrl("http://www.xxx.com");
入口方法傳入: EasyHttp.get("/v1/app/chairdressing/skinAnalyzePower/skinTestResult").baseUrl("http://www.xxxx.com")
如果入口方法中傳入的url含有http或者https,則不會拼接初始化設置的baseUrl.
例如:EasyHttp.get("http://www.xxx.com/v1/app/chairdressing/skinAnalyzePower/skinTestResult")則setBaseUrl()和baseUrl()傳入的baseurl都不會被拼接。
注:EasyHttp.get/post/put/等采用拼接的用法時請注意,url要用/斜杠開頭,例如:EasyHttp.get("/v1/login") 正確 EasyHttp.get("v1/login") 錯誤

http請求參數

兩種設置方式
.params(HttpParams params)
.params("param1","param1Value")//添加參數鍵值對

HttpParams params = new HttpParams();
params.put("appId", AppConstant.APPID);
.addCommonParams(params)//設置全局公共參數

http請求頭

.headers(HttpHeaders headers)
.headers("header2","header2Value")//添加參數鍵值對

.addCommonHeaders(headers)//設置全局公共頭

普通網絡請求

支持get/post/delete/put等
鏈式調用的終點請求的執行方式有:execute(Classclazz) 、execute(Type type)、execute(CallBackcallBack)三種方式,都是針對標準的ApiResult

execute(CallBackcallBack)

1.EasyHttp(推薦)
示例:
方式一:
//EasyHttp.post("/v1/app/chairdressing/skinAnalyzePower/skinTestResult")
EasyHttp.get("/v1/app/chairdressing/skinAnalyzePower/skinTestResult")

.readTimeOut(30 * 1000)//局部定義讀超時.writeTimeOut(30 * 1000).connectTimeout(30 * 1000).params("name","張三").timeStamp(true).execute(new SimpleCallBack<SkinTestResult>() {@Overridepublic void onError(ApiException e) {showToast(e.getMessage());}@Overridepublic void onSuccess(SkinTestResult response) {if (response != null) showToast(response.toString());}});

2.手動創建請求對象
//GetRequest 、PostRequest、DeleteRequest、PutRequest
GetRequest request = new GetRequest("/v1/app/chairdressing/skinAnalyzePower/skinTestResult");

request.readTimeOut(30 * 1000)//局部定義讀超時.params("param1", "param1Value1").execute(new SimpleCallBack<SkinTestResult>() {@Overridepublic void onError(ApiException e) {}@Overridepublic void onSuccess(SkinTestResult response) {}});

execute(Classclazz)和execute(Type type)

execute(Classclazz)和execute(Type type)功能基本一樣,execute(Type type)主要是針對集合不能直接傳遞Class
EasyHttp.get(url)

.params("param1", "paramValue1").execute(SkinTestResult.class)//非常簡單直接傳目標class//.execute(new TypeToken<List<SectionItem>>() {}.getType())//Type類型.subscribe(new BaseSubscriber<SkinTestResult>() {@Overridepublic void onError(ApiException e) {showToast(e.getMessage());}@Overridepublic void onNext(SkinTestResult skinTestResult) {showToast(skinTestResult.toString());}});

請求返回Disposable

網絡請求會返回Disposable對象,方便取消網絡請求
Disposable disposable = EasyHttp.get("/v1/app/chairdressing/skinAnalyzePower/skinTestResult")

.params("param1", "paramValue1").execute(new SimpleCallBack<SkinTestResult>() {@Overridepublic void onError(ApiException e) {showToast(e.getMessage());}@Overridepublic void onSuccess(SkinTestResult response) {showToast(response.toString());}});//在需要取消網絡請求的地方調用,一般在onDestroy()中//EasyHttp.cancelSubscription(disposable);

帶有進度框的請求

帶有進度框的請求,可以設置對話框消失是否自動取消網絡和自定義對話框功能,具體參數作用請看請求回調講解

方式一:ProgressDialogCallBack

ProgressDialogCallBack帶有進度框的請求,可以設置對話框消失是否自動取消網絡和自定義對話框功能,具體參數作用請看自定義CallBack講解
IProgressDialog mProgressDialog = new IProgressDialog() {

@Overridepublic Dialog getDialog() {ProgressDialog dialog = new ProgressDialog(MainActivity.this);dialog.setMessage("請稍候...");return dialog;}};EasyHttp.get("/v1/app/chairdressing/").params("param1", "paramValue1").execute(new ProgressDialogCallBack<SkinTestResult>(mProgressDialog, true, true) {@Overridepublic void onError(ApiException e) {super.onError(e);//super.onError(e)必須寫不能刪掉或者忘記了//請求失敗}@Overridepublic void onSuccess(SkinTestResult response) {//請求成功}});

注:錯誤回調 super.onError(e);必須寫

方式二:ProgressSubscriber
IProgressDialog mProgressDialog = new IProgressDialog() {

@Overridepublic Dialog getDialog() {ProgressDialog dialog = new ProgressDialog(MainActivity.this);dialog.setMessage("請稍候...");return dialog;}};

EasyHttp.get(URL)

.timeStamp(true).execute(SkinTestResult.class).subscribe(new ProgressSubscriber<SkinTestResult>(this, mProgressDialog) {@Overridepublic void onError(ApiException e) {super.onError(e);showToast(e.getMessage());}@Overridepublic void onNext(SkinTestResult skinTestResult) {showToast(skinTestResult.toString());}});

請求返回Observable

通過網絡請求可以返回Observable,這樣就可以很好的通過Rxjava與其它場景業務結合處理,甚至可以通過Rxjava的connect()操作符處理多個網絡請求。例如:在一個頁面有多個網絡請求,如何在多個請求都訪問成功后再顯示頁面呢?這也是Rxjava強大之處。
注:目前通過execute(Classclazz)方式只支持標注的ApiResult結構,不支持自定義的ApiResult
示例:
Observable observable = EasyHttp.get(url)

.params("param1", "paramValue1").execute(SkinTestResult.class);observable.subscribe(new BaseSubscriber<SkinTestResult>() {@Overridepublic void onError(ApiException e) {showToast(e.getMessage());}@Overridepublic void onNext(SkinTestResult skinTestResult) {showToast(skinTestResult.toString());}});

文件下載

本庫提供的文件下載非常簡單,沒有提供復雜的下載方式例如:下載管理器、斷點續傳、多線程下載等,因為不想把本庫做重。如果復雜的下載方式,還請考慮其它下載方案。
文件目錄如果不指定,默認下載的目錄為/storage/emulated/0/Android/data/包名/files
文件名如果不指定,則按照以下規則命名:

1.首先檢查用戶是否傳入了文件名,如果傳入,將以用戶傳入的文件名命名
2.如果沒有傳入文件名,默認名字是時間戳生成的。
3.如果傳入了文件名但是沒有后綴,程序會自動解析類型追加后綴名

示例:
String url = "http://61.144.207.146:8081/b8154d3d-4166-4561-ad8d-7188a96eb195/2005/07/6c/076ce42f-3a78-4b5b-9aae-3c2959b7b1ba/kfid/2475751/qqlite_3.5.0.660_android_r108360_GuanWang_537047121_release_10000484.apk";

EasyHttp.downLoad(url).savePath("/sdcard/test/QQ").saveName("release_10000484.apk")//不設置默認名字是時間戳生成的.execute(new DownloadProgressCallBack<String>() {@Overridepublic void update(long bytesRead, long contentLength, boolean done) {int progress = (int) (bytesRead * 100 / contentLength);HttpLog.e(progress + "% ");dialog.setProgress(progress);if (done) {//下載完成}...}@Overridepublic void onStart() {//開始下載}@Overridepublic void onComplete(String path) {//下載完成,path:下載文件保存的完整路徑}@Overridepublic void onError(ApiException e) {//下載失敗}});

POST請求,上傳String、json、object、body、byte[]

一般此種用法用于與服務器約定的數據格式,當使用該方法時,params中的參數設置是無效的,所有參數均需要通過需要上傳的文本中指定,此外,額外指定的header參數仍然保持有效。

?.upString("這是要上傳的長文本數據!")//默認類型是:MediaType.parse("text/plain")

?如果你對請求頭有自己的要求,可以使用這個重載的形式,傳入自定義的content-type文本
upString("這是要上傳的長文本數據!", "application/xml") // 比如上傳xml數據,這里就可以自己指定請求頭

?upJson該方法與upString沒有本質區別,只是數據格式是json,通常需要自己創建一個實體bean或者一個map,把需要的參數設置進去,然后通過三方的Gson或者 fastjson轉換成json字符串,最后直接使用該方法提交到服務器。
.upJson(jsonObject.toString())//上傳json

?.upBytes(new byte[]{})//上傳byte[]

?.requestBody(body)//上傳自定義RequestBody

?.upObject(object)//上傳對象object 必須要增加.addConverterFactory(GsonConverterFactory.create())設置

1.upString、upJson、requestBody、upBytes、upObject五個方法不能同時使用,當前只能選用一個
2.使用upJson、upObject時候params、sign(true/false)、accessToken(true/false)、攔截器都不會起作用

示例:
HashMap params = new HashMap<>();
params.put("key1", "value1");
params.put("key2", "這里是需要提交的json格式數據");
params.put("key3", "也可以使用三方工具將對象轉成json字符串");
JSONObject jsonObject = new JSONObject(params);

RequestBody body=RequestBody.create(MediaType.parse("xxx/xx"),"內容");
EasyHttp.post("v1/app/chairdressing/news/favorite")

//.params("param1", "paramValue1")//不能使用params,upString 與 params 是互斥的,只有 upString 的數據會被上傳.upString("這里是要上傳的文本!")//默認類型是:MediaType.parse("text/plain")//.upString("這是要上傳的長文本數據!", "application/xml") // 比如上傳xml數據,這里就可以自己指定請求頭//.upJson(jsonObject.toString())//.requestBody(body)//.upBytes(new byte[]{})//.upObject(object).execute(new SimpleCallBack<String>() {@Overridepublic void onError(ApiException e) {showToast(e.getMessage());}@Overridepublic void onSuccess(String response) {showToast(response);}});

源碼地址:https://github.com/zhou-you/RxEasyHttp
原文地址:http://www.apkbus.com/blog-151006-78095.html
篇幅所限,完整內容可點擊左下角“閱讀原文”查看。

原文發布時間為:2018-06-28
本文作者:zhouy478319399
本文來自云棲社區合作伙伴“安卓巴士Android開發者門戶”,了解相關信息可以關注“安卓巴士Android開發者門戶”。

總結

以上是生活随笔為你收集整理的一款基于RxJava2+Retrofit2实现简单易用的网络请求框架的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: av首页在线 | 午夜日韩电影 | av香港经典三级级 在线 | 欧美自拍偷拍一区二区 | 91国产在线免费观看 | 亚洲欧美综合网 | 精东传媒在线观看 | 国语精品 | 国产亚洲精久久久久久无码苍井空 | 一级免费黄色大片 | 国产精品久久久久桃色tv | 国产内射一区二区 | 日韩精品一区二区三区视频在线观看 | 免费观看h片 | 剧情av在线 | 太久av| 麻豆精品在线看 | 久草视频在线免费看 | 成年人在线观看视频网站 | 三上悠亚激情av一区二区三区 | 波多野结衣 久久 | 91成人在线免费观看 | 久久久久无码精品国产sm果冻 | av手机天堂 | 午夜影院日本 | 精品国产免费无码久久久 | 国产一区二区三区精品愉拍 | 国产日韩成人 | 国产精彩视频一区二区 | 波多野吉衣av无码 | 亚洲第一天堂av | 欧美狠狠干 | av鲁丝一区鲁丝二区鲁丝 | 主播福利在线 | 91尤物在线 | 国产精品一区二区不卡 | 爱爱视频网址 | 日韩av首页 | 日韩高清免费av | 亚洲精品伊人 | jvid视频| 蜜乳av中文字幕 | 国产免费高清视频 | 亚洲 在线 | 日韩中文字幕在线 | 99re在线观看| 成人免费毛片aaaaaa片 | 午夜宅男影院 | 人妖ts福利视频一二三区 | 丁香花高清在线观看完整动漫 | 91亚洲精品一区二区乱码 | 午夜色图 | 二区视频在线 | 久色视频在线 | 国偷自产av一区二区三区麻豆 | 成人在线午夜 | 中文在线最新版天堂 | 成人网导航 | 国产亚洲精品精品精品 | 久久久视频在线观看 | 亚洲精品高潮久久久久久久 | 天堂av观看 | 亚洲色精品三区二区一区 | 免费黄色小说视频 | 高清无码视频直接看 | 国内精品一区二区 | 欧美黑人添添高潮a片www | 色批网站| 久久夜色精品国产噜噜亚洲av | 99超碰在线观看 | 欧洲一区二区 | 亚洲精品欧洲 | 色网站观看 | 日日躁夜夜躁白天躁晚上躁91 | 欧美自拍一区 | 91麻豆蜜桃| 中文字幕在线视频免费播放 | 久久精品免费观看 | 成人少妇影院yyyy | 毛片直接看| 国产大片在线观看 | 污网在线观看 | 香蕉在线网站 | 乌克兰极品av女神 | 一级一毛片 | 一级黄色录象 | 超碰资源在线 | 户外少妇对白啪啪野战 | 色视频在线观看免费 | 98成人网| 久久精品九九 | 日本成人片网站 | 美国av毛片 | 超碰www| 黑人日批视频 | 韩国黄色视屏 | а√天堂资源在线 | 精品人妻一区二区三区久久嗨 | 国产av无码专区亚洲av |