亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Retrofit2.0使用詳解

2019-11-09 14:27:35
字體:
來源:轉載
供稿:網友

綜述

  retrofit是由square公司開發的。square在github上發布了很多優秀的Android開源項目。例如:otto(事件總線),leakcanary(排查內存泄露),android-times-square(日歷控件),dagger(依賴注入),picasso(異步加載圖片),okhttp(網絡請求),retrofit(網絡請求)等等。更多square上的開源項目我們可以去square的GitHub進行查看。這次就來介紹一下retrofit的一些基本用法。retrofit是REST安卓客戶端請求庫。使用retrofit可以進行GET,POST,PUT,DELETE等請求方式。下面就來看一下retrofit的基本用法。

Retrofit使用方法

  由于retrofit2.0與先前版本的差別還是比較大,對于不同版本之間的差異在這里就不在進行詳細區別。下面的例子也是針對于retrofit2.0進行介紹的。retrofit2.0它依賴于OkHttp,而且這部分也不再支持替換。在這里我們也不需要顯示的導入okHttp,在retrofit中已經導入okhttp3。

<dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>mockwebserver</artifactId> <scope>test</scope></dependency>1234512345

  在下面的例子當中采用與GitHub一些相關api進行演示。在這里首先需要添加訪問網絡的權限。

<uses-permission android:name="android.permission.INTERNET"/>11

簡單示例

添加Gradle依賴項

  在這里我們最好查看一下retrofit的官網添加最新依賴。

compile 'com.squareup.retrofit2:retrofit:2.0.1'11

創建API接口

  在retrofit中通過一個java接口作為http請求的api接口。

public interface GitHubApi { @GET("repos/{owner}/{repo}/contributors") Call<ResponseBody> contributorsBySimpleGetCall(@Path("owner") String owner, @Path("repo") String repo);}1234512345

創建retrofit實例

  在這里baseUrl是在創建retrofit實力的時候定義的,我們也可以在API接口中定義完整的url。在這里建議在創建baseUrl中以”/”結尾,在API中不以”/”開頭和結尾。

Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .build();123123

調用API接口

  在調用API接口請求后,獲得一個json字符串,通過Gson進行解析,獲得login以及contributions。

GitHubApi repo = retrofit.create(GitHubApi.class); Call<ResponseBody> call = repo.contributorsBySimpleGetCall(mUserName, mRepo);call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { try { Gson gson = new Gson(); ArrayList<Contributor> contributorsList = gson.fromJson(response.body().string(), new TypeToken<List<Contributor>>(){}.getType()); for (Contributor contributor : contributorsList){ Log.d("login",contributor.getLogin()); Log.d("contributions",contributor.getContributions()+""); } } catch (IOException e) { e.PRintStackTrace(); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { }});12345678910111213141516171819202122231234567891011121314151617181920212223

效果展示

  這樣就完成了一個http請求,上面請求的完整地址為:https://api.github.com/repos/square/retrofit/contributors   然后我們看一下運行結果: 這里寫圖片描述

取消請求

  我們可以終止一個請求。終止操作是對底層的httpclient執行cancel操作。即使是正在執行的請求,也能夠立即終止。

call.cancel();11

轉換器

  在上面的例子中通過獲取ResponseBody后,我們自己使用Gson來解析接收到的Json格式數據。在Retrofit中當創建一個Retrofit實例的時候可以為其添加一個Json轉換器,這樣就會自動將Json格式的響應體轉換為所需要的Java對象。那么先來看一下如何根據已有的Json格式數據如何生成Java對象。當然我們可以根據已知的數據手動創建Java對象,也可以通過工具更具Json格式為我們自動生成Java對象。

自動生成Java對象

  在這里介紹兩種根據Json數據自動生成Java對象的工具。

jsonschema2pojo

  可以通過訪問jsonschema2pojo網站。先來看一下它的使用方法。 這里寫圖片描述  上面配置中所選注解若是使用的Gson解析,可以選擇Gson,當然沒有也是可以的。對于@Generated注解若是需要保留的話添加如下依賴,也可以直接刪除@Generated注解,沒有任何影響。

compile 'org.glassfish:javax.annotation:10.0-b28'11

GsonFormat

  GsonFormat是AndroidStudio中的一個插件,在AndroidStudio的插件選項中直接搜索安裝這個插件即可。在這里看一下是如何使用這個插件的。 這里寫圖片描述

添加轉換器

  在這里我們需要為retrofit添加gson轉換器的依賴。添加過converter-gson后不用再添加gson庫。在converter-gson中已經包含gson。

compile 'com.squareup.retrofit2:converter-gson:2.0.1'11

  在這里先創建一個Java類Contributor,用來保存接收到的數據。

public class Contributor { private String login; private Integer contributions; public String getLogin() { return login; } public void setLogin(String login) { this.login = login; } public Integer getContributions() { return contributions; } public void setContributions(Integer contributions) { this.contributions = contributions; }}12345678910111213141516171819201234567891011121314151617181920

  這時候修改我們的API接口。

@GET("repos/{owner}/{repo}/contributors")Call<List<Contributor>> contributorsByAddConverterGetCall(@Path("owner") String owner, @Path("repo") String repo);1212

  創建retrofit實例,我們通過addConverterFactory指定一個factory來對響應反序列化,在這里converters被添加的順序將是它們被Retrofit嘗試的順序。

Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .addConverterFactory(GsonConverterFactory.create()) .build();12341234

  調用上面所修改的API接口。

GitHubApi repo = retrofit.create(GitHubApi.class);Call<List<Contributor>> call = repo.contributorsByAddConverterGetCall(mUserName, mRepo);call.enqueue(new Callback<List<Contributor>>() { @Override public void onResponse(Call<List<Contributor>> call, Response<List<Contributor>> response) { List<Contributor> contributorList = response.body(); for (Contributor contributor : contributorList){ Log.d("login", contributor.getLogin()); Log.d("contributions", contributor.getContributions() + ""); } } @Override public void onFailure(Call<List<Contributor>> call, Throwable t) { }});12345678910111213141516171234567891011121314151617

  最后在來看一下運行結果。 這里寫圖片描述  retrofit不僅僅只支持gson,還支持其他許多json解析庫。以下版本號需要與retrofit版本號保持一致,并且以retrofit官網給出的版本號為準。

Gson: compile 'com.squareup.retrofit2:converter-gson:2.0.1'Jackson: compile 'com.squareup.retrofit2:converter-jackson:2.0.1'Moshi: compile 'com.squareup.retrofit2:converter-moshi:2.0.1'Protobuf: compile 'com.squareup.retrofit2:converter-protobuf:2.0.1'Wire: compile 'com.squareup.retrofit2:converter-wire:2.0.1'Simple xmlcompile 'com.squareup.retrofit2:converter-simplexml:2.0.1'Scalars (primitives, boxed, and String): compile 'com.squareup.retrofit2:converter-scalars:2.0.1'

增加日志信息

  在retrofit2.0中是沒有日志功能的。但是retrofit2.0中依賴OkHttp,所以也就能夠通過OkHttp中的interceptor來實現實際的底層的請求和響應日志。在這里我們需要修改上一個retrofit實例,為其自定自定義的OkHttpClient。代碼如下:

HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(httpLoggingInterceptor) .build();Retrofit retrofit = new Retrofit.Builder().addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .client(okHttpClient) .baseUrl("https://api.github.com/") .addConverterFactory(GsonConverterFactory.create()) .build();12345678910111234567891011

  還需要添加如下依賴。

compile 'com.squareup.okhttp3:logging-interceptor:3.1.2'11

  其他代碼沒有任何變化,我們來看一下運行結果。 這里寫圖片描述

添加請求頭

  我們可以通過@Headers來添加請求頭。

@Headers({ "Accept: application/vnd.github.v3.full+json", "User-Agent: RetrofitBean-Sample-App", "name:ljd"})@GET("repos/{owner}/{repo}/contributors")Call<List<Contributor>> contributorsAndAddHeader(@Path("owner") String owner,@Path("repo") String repo);12345671234567

  運行結果。 這里寫圖片描述

同步請求

  在這里我們可以直接通過call.execute()執行一個同步請求,由于不允許在主線程中進行網絡請求操作,所以我們需要再子線程中進行執行。

new Thread(new Runnable() { @Override public void run() { try { Response<List<Contributor>> response = call.execute(); List<Contributor> contributorsList = response.body(); for (Contributor contributor : contributorsList){ Log.d("login",contributor.getLogin()); Log.d("contributions",contributor.getContributions()+""); } } catch (IOException e) { e.printStackTrace(); } }}).start();1234567891011121314151612345678910111213141516

  在這里看一下運行結果。 這里寫圖片描述

clone

  在這里無論是同步操作還是異步操作每一個call對象實例只能被執行一次。多次執行拋出如下異常。 這里寫圖片描述  在這里如果我們的request和respone都是一一對應的。我們通過Clone方法創建一個一模一樣的實例,并且它的開銷也是很小的。

Call<List<Contributor>> cloneCall = call.clone();cloneCall.execute();1212

get請求

  在前面的一些例子當中我們都是采用get請求。當然我們也可以為URL指定查詢參數。使用@Query即可。

@GET("search/repositories")Call<RetrofitBean> queryRetrofitByGetCall(@Query("q")String owner, @Query("since")String time, @Query("page")int page, @Query("per_page")int per_Page);1234512345

  當我們的參數過多的時候我們可以通過@QueryMap注解和map對象參數來指定每個表單項的Key,value的值。

@GET("search/repositories")Call<RetrofitBean> queryRetrofitByGetCallMap(@QueryMap Map<String,String> map);1212

  下面的call對象實例為上面api中所返回call對象。更具所返回的json數據所創建的實體類在這里就不在貼出代碼,下載源碼詳細查看。

call.enqueue(new Callback<RetrofitBean>() { @Override public void onResponse(Call<RetrofitBean> call, Response<RetrofitBean> response) { RetrofitBean retrofit = response.body(); List<Item> list = retrofit.getItems(); if (list == null) return; Log.d(TAG, "total:" + retrofit.getTotalCount()); Log.d(TAG, "incompleteResults:" + retrofit.getIncompleteResults()); Log.d(TAG, "----------------------"); for (Item item : list) { Log.d(TAG, "name:" + item.getName()); Log.d(TAG, "full_name:" + item.getFull_name()); Log.d(TAG, "description:" + item.getDescription()); Owner owner = item.getOwner(); Log.d(TAG, "login:" + owner.getLogin()); Log.d(TAG, "type:" + owner.getType()); } } @Override public void onFailure(Call<RetrofitBean> call, Throwable t) { }});12345678910111213141516171819202122232425261234567891011121314151617181920212223242526

  上面請求中的完整連接為: https://api.github.com/search/repositories?q=retrofit&since=2016-03-29&page=1&per_page=3,運行結果如下。 這里寫圖片描述

  在Retrofit 2.0添加了一個新的注解:@Url,它允許我們直接傳入一個請求的URL。這樣以來我們可以將上一個請求的獲得的url直接傳入進來。方便了我們的操作。

@GETCall<List<Contributor>> repoContributorsPaginate(@Url String url);1212

Form encoded和Multipart

Form encoded

  我們可以使用@FormUrlEncoded注解來發送表單數據。使用 @Field注解和參數來指定每個表單項的Key,value為參數的值。

@FormUrlEncoded@POST("user/edit")Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);123123

  當我們有很多個表單參數時可以通過@FieldMap注解和Map對象參數來指定每個表單項的Key,value的值。

@FormUrlEncoded@POST("user/edit")Call<User> updateUser(@FieldMap Map<String,String> fieldMap);123123

Multipart

  我們還可以通過@Multipart注解來發送Multipart數據。通過@Part注解來定義需要發送的文件。

@Multipart@PUT("/user/photo")User updateUser(@Part("photo") TypedFile photo, @Part("description") TypedString description);123123

Retrofit與RxJava結合

  Retrofit能夠與RxJava進行完美結合。下面就來看一下Retrofit與RxJava是如何結合在一起的。對于RxJava在這就不在進行詳細介紹,對于RXJava的使用可以參考附錄里面給出鏈接。   首先我們需要添加如下依賴。

compile 'com.squareup.retrofit2:adapter-rxjava:2.0.1'compile 'io.reactivex:rxandroid:1.1.0'1212

  創建retrofit對象實例時,通過addCallAdapterFactory來添加對RxJava的支持。

HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);OkHttpClient okHttpClient = new OkHttpClient.Builder() .addInterceptor(httpLoggingInterceptor) .build();Retrofit retrofit = new Retrofit.Builder() .client(okHttpClient) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .baseUrl("https://api.github.com/") .build();12345678910111234567891011

  使用Observable創建一個API接口。

@GET("repos/{owner}/{repo}/contributors")Observable<List<Contributor>> contributorsByRxJava(@Path("owner") String owner,@Path("repo") String repo);1212

  下面來調用這個API接口。

private CompositeSubscription mSubscriptions = new CompositeSubscription();11mSubscriptions.add( mGitHubService.contributorsByRxJava(mUserName, mRepo) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<List<Contributor>>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(List<Contributor> contributors) { for (Contributor c : contributors) { Log.d("TAG", "login:" + c.getLogin() + " contributions:" + c.getContributions()); } } }));12345678910111213141516171819201234567891011121314151617181920

  下面來看一下運行結果。 這里寫圖片描述  如果我們想要查看所有contributor的信息,首先我們需要向gitHub請求獲取到所有contributor,然后再通過獲得contributor進行依次向github請求獲取contributor的信息,在這時候我們使用RxJava也就非常方便了。下面看一下如何操作的。   首先再添加一個API接口。

@GET("repos/{owner}/{repo}/contributors")Observable<List<Contributor>> contributorsByRxJava(@Path("owner") String owner, @Path("repo") String repo);123123

  下面在看一下是如何進行根據獲得的contributor來查看contributor的信息。

mSubscriptions.add(mGitHubService.contributorsByRxJava(mUserName, mRepo) .flatMap(new Func1<List<Contributor>, Observable<Contributor>>() { @Override public Observable<Contributor> call(List<Contributor> contributors) { return Observable.from(contributors); } }) .flatMap(new Func1<Contributor, Observable<Pair<User, Contributor>>>() { @Override public Observable<Pair<User, Contributor>> call(Contributor contributor) { Observable<User> userObservable = mGitHubService.userByRxJava(contributor.getLogin()) .filter(new Func1<User, Boolean>() { @Override public Boolean call(User user) { return !isEmpty(user.getName()) && !isEmpty(user.getEmail()); } }); return Observable.zip(userObservable, Observable.just(contributor), new Func2<User, Contributor, Pair<User, Contributor>>() { @Override public Pair<User, Contributor> call(User user, Contributor contributor) { return new Pair<>(user, contributor); } }); } }) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<Pair<User, Contributor>>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(Pair<User, Contributor> pair) { User user = pair.first; Contributor contributor = pair.second; Log.d(TAG, "name:" + user.getName()); Log.d(TAG, "contributions:" + contributor.getContributions()); Log.d(TAG, "email:" + user.getEmail()); } }));123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051

  最后在來看下運行結果。 這里寫圖片描述

Retrofit設置緩存

對Retrofit設置緩存,由于Retrofit是對OkHttp的封裝,所以我們可以直接通過OkHttpClient著手。也就是為OkHttp設置緩存。設置緩存代碼如下所示。

private OkHttpClient getCacheOkHttpClient(Context context){ final File baseDir = context.getCacheDir(); final File cacheDir = new File(baseDir, "HttpResponseCache"); Timber.e(cacheDir.getAbsolutePath()); Cache cache = new Cache(cacheDir, 10 * 1024 * 1024); //緩存可用大小為10M Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = chain -> { Request request = chain.request(); if(!NetWorkUtils.isNetWorkAvailable(context)){ request = request.newBuilder() .cacheControl(CacheControl.FORCE_CACHE) .build(); } Response originalResponse = chain.proceed(request); if (NetWorkUtils.isNetWorkAvailable(context)) { int maxAge = 60; //在線緩存一分鐘 return originalResponse.newBuilder() .removeHeader("Pragma") .removeHeader("Cache-Control") .header("Cache-Control", "public, max-age=" + maxAge) .build(); } else { int maxStale = 60 * 60 * 24 * 4 * 7; //離線緩存4周 return originalResponse.newBuilder() .removeHeader("Pragma") .removeHeader("Cache-Control") .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) .build(); } }; return new OkHttpClient.Builder() .addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR) .addInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR) .cache(cache) .build();}123456789101112131415161718192021222324252627282930313233343536373839123456789101112131415161718192021222324252627282930313233343536373839

總結

  在retrofit的使用中,對于文件你上傳與下載,并沒有為我們提供進度更新的接口,在這里就需要我們自己處理了。在下面的例子中給出一個文件下載的例子,并且對下載進度更新通過logcat打印出來??梢韵螺d進行查看。到這里retrofit的基本用法也就介紹完了,對于retrofit更多的好處在使用中我們可以慢慢體會。

源碼下載

附錄

Retrofit官方文檔用 Retrofit 2 簡化 HTTP 請求給 Android 開發者的 RxJava 詳解RxJava Essentials 中文翻譯
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美亚洲免费电影| 日韩毛片在线观看| 欧美午夜影院在线视频| 久久伊人色综合| 国产精品自拍视频| 亚洲午夜小视频| 国产一区二区丝袜高跟鞋图片| 欧美成人中文字幕在线| 欧美日韩国产综合新一区| 亚洲iv一区二区三区| 欧美极品少妇xxxxⅹ裸体艺术| 色系列之999| 欧美丰满少妇xxxxx做受| 91av免费观看91av精品在线| 亚洲va男人天堂| 91av福利视频| 日韩中文字幕视频| 久久国产精品网站| 国产91精品在线播放| 成人黄色在线播放| 欧美中文字幕在线观看| 日韩网站免费观看高清| 久久久精品久久久久| 欧美日韩激情视频8区| 欧美激情精品久久久久久蜜臀| 高清视频欧美一级| 激情懂色av一区av二区av| 久久精品视频导航| 欧美精品video| 伊人久久男人天堂| 国产精品美女在线观看| 91久久国产精品91久久性色| 九九精品在线播放| 性欧美xxxx交| 国产福利精品在线| 欧美日韩国产综合视频在线观看中文| 亚洲香蕉av在线一区二区三区| 亚洲国产欧美一区二区三区久久| 超碰精品一区二区三区乱码| 91精品在线一区| 成人久久久久爱| 九九热在线精品视频| 国产精品99久久久久久www| 综合激情国产一区| 亚洲欧美国产一区二区三区| 亚洲日本欧美中文幕| 国产精品jvid在线观看蜜臀| 久久国产精品久久久久| 亚洲三级黄色在线观看| 国产v综合ⅴ日韩v欧美大片| 久久夜色精品国产欧美乱| 久久久久五月天| 2020欧美日韩在线视频| 欧美激情精品久久久久久黑人| 91色p视频在线| 色偷偷偷亚洲综合网另类| 亚洲网在线观看| 欧美日韩精品在线播放| 国产欧美 在线欧美| 日韩成人av在线| 日本在线精品视频| 亚洲精品免费av| 日韩欧美在线中文字幕| 国产精品自拍小视频| 午夜免费在线观看精品视频| 成人久久久久爱| 好吊成人免视频| 夜夜嗨av色一区二区不卡| 琪琪亚洲精品午夜在线| 欧美黑人视频一区| 国产成人综合亚洲| 亚洲国产第一页| 国产91ⅴ在线精品免费观看| 成人激情综合网| 亚洲精品国精品久久99热一| 91精品视频在线看| 一本色道久久88综合亚洲精品ⅰ| 69久久夜色精品国产69乱青草| 日本欧美一级片| 久久午夜a级毛片| 欧美激情欧美激情在线五月| 欧美激情视频免费观看| 亚洲一级黄色av| 欧美极品美女电影一区| 91久久在线观看| 亚洲久久久久久久久久| 国产成人涩涩涩视频在线观看| 黑人精品xxx一区一二区| 亚洲高清不卡av| 欧美日韩在线观看视频小说| 国产a∨精品一区二区三区不卡| 国产精品久久久久久久app| 久久久精品视频成人| 国产亚洲欧美日韩精品| 日韩电影在线观看免费| 国自在线精品视频| 国外成人在线播放| 国产精品老女人精品视频| 久久精品一本久久99精品| 欧美丝袜美女中出在线| 69**夜色精品国产69乱| 91中文精品字幕在线视频| 日韩精品视频在线播放| 欧美精品电影在线| 亚洲欧洲在线观看| 97人人爽人人喊人人模波多| 欧美午夜影院在线视频| 欧美日韩国产一区二区| 国产美女高潮久久白浆| 久久精品91久久香蕉加勒比| 久久精品电影网站| 欧美一区深夜视频| 91精品国产777在线观看| 爽爽爽爽爽爽爽成人免费观看| 欧美黑人视频一区| 揄拍成人国产精品视频| 中文字幕日韩av电影| 欧美最猛黑人xxxx黑人猛叫黄| 亚洲午夜精品久久久久久性色| 国产欧美欧洲在线观看| 欧美精品做受xxx性少妇| 日韩av在线影院| 久久伊人免费视频| 97精品国产91久久久久久| 狠狠躁天天躁日日躁欧美| 国产亚洲精品美女久久久久| 成人免费在线视频网址| 亚洲精品一区二区三区婷婷月| 92福利视频午夜1000合集在线观看| 国产精品视频99| 成年人精品视频| 亚洲一区二区三区视频播放| 欧美大全免费观看电视剧大泉洋| 日韩福利视频在线观看| 日韩免费av一区二区| 91亚洲va在线va天堂va国| 亚洲国产高清高潮精品美女| 一本久久综合亚洲鲁鲁| 久久伊人免费视频| 亚洲国产精品成人一区二区| 色噜噜狠狠色综合网图区| 亚洲一区999| 欧美精品videos| 久久成人18免费网站| 国产精品白嫩美女在线观看| 亚洲精品免费一区二区三区| 亚洲欧美日韩国产成人| 亚洲成人av片在线观看| 精品一区二区电影| 国产精品香蕉国产| 国产精品视频精品| 日韩av网站电影| 成人a在线观看| 亚洲毛片在线免费观看| 亚洲社区在线观看| 久久久99免费视频| 国内精品400部情侣激情| www.亚洲免费视频| 亚洲欧美日韩精品| 岛国av午夜精品| 91chinesevideo永久地址| 久久精品最新地址| 亚洲男人天天操| 自拍视频国产精品|