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

Android模塊化探索與實踐

移動開發 Android
萬維網發明人 Tim Berners-Lee 談到設計原理時說過:“簡單性和模塊化是軟件工程的基石;分布式和容錯性是互聯網的生命。” 由此可見模塊化之于軟件工程領域的重要性。

前言

萬維網發明人 Tim Berners-Lee 談到設計原理時說過:“簡單性和模塊化是軟件工程的基石;分布式和容錯性是互聯網的生命。” 由此可見模塊化之于軟件工程領域的重要性。

從 2016 年開始,模塊化在 Android 社區越來越多的被提及。隨著移動平臺的不斷發展,移動平臺上的軟件慢慢走向復雜化,體積也變得臃腫龐大;為了降低大型軟件復雜性和耦合度,同時也為了適應模塊重用、多團隊并行開發測試等等需求,模塊化在 Android 平臺上變得勢在必行。阿里 Android 團隊在年初開源了他們的容器化框架 Atlas 就很大程度說明了當前 Android 平臺開發大型商業項目所面臨的問題。

什么是模塊化

那么什么是模塊化呢?《 Java 應用架構設計:模塊化模式與 OSGi 》一書中對它的定義是:模塊化是一種處理復雜系統分解為更好的可管理模塊的方式。

上面這種描述太過生澀難懂,不夠直觀。下面這種類比的方式則可能加容易理解。

我們可以把軟件看做是一輛汽車,開發一款軟件的過程就是生產一輛汽車的過程。一輛汽車由車架、發動機、變數箱、車輪等一系列模塊組成;同樣,一款大型商業軟件也是由各個不同的模塊組成的。

汽車的這些模塊是由不同的工廠生產的,一輛 BMW 的發動機可能是由位于德國的工廠生產的,它的自動變數箱可能是 Jatco(世界三大變速箱廠商之一)位于日本的工廠生產的,車輪可能是中國的工廠生產的,***交給華晨寶馬的工廠統一組裝成一輛完整的汽車。這就類似于我們在軟件工程領域里說的多團隊并行開發,***將各個團隊開發的模塊統一打包成我們可使用的 App 。

一款發動機、一款變數箱都不可能只應用于一個車型,比如同一款 Jatco 的 6AT 自動變速箱既可能被安裝在 BMW 的車型上,也可能被安裝在 Mazda 的車型上。這就如同軟件開發領域里的模塊重用。

到了冬天,特別是在北方我們可能需要開著車走雪路,為了安全起見往往我們會將汽車的公路胎升級為雪地胎;輪胎可以很輕易的更換,這就是我們在軟件開發領域談到的低耦合。一個模塊的升級替換不會影響到其它模塊,也不會受其它模塊的限制;同時這也類似于我們在軟件開發領域提到的可插拔。

模塊化分層設計

上面的類比很清晰的說明的模塊化帶來的好處:

  • 多團隊并行開發測試;
  • 模塊間解耦、重用;
  • 可單獨編譯打包某一模塊,提升開發效率。

在《安居客 Android 項目架構演進》這篇文章中,我介紹了安居客 Android 端的模塊化設計方案,這里我還是拿它來舉例。但首先要對本文中的組件和模塊做個區別定義

  • 組件:指的是單一的功能組件,如地圖組件(MapSDK)、支付組件(AnjukePay)、路由組件(Router)等等;
  • 模塊:指的是獨立的業務模塊,如新房模塊(NewHouseModule)、二手房模塊(SecondHouseModule)、即時通訊模塊(InstantMessagingModule)等等;模塊相對于組件來說粒度更大。

具體設計方案如下圖:

Android模塊化探索與實踐

整個項目分為三層,從下至上分別是:

  • Basic Component Layer: 基礎組件層,顧名思義就是一些基礎組件,包含了各種開源庫以及和業務無關的各種自研工具庫;
  • Business Component Layer: 業務組件層,這一層的所有組件都是業務相關的,例如上圖中的支付組件 AnjukePay、數據模擬組件 DataSimulator 等等;
  • Business Module Layer: 業務 Module 層,在 Android Studio 中每塊業務對應一個單獨的 Module。例如安居客用戶 App 我們就可以拆分成新房 Module、二手房 Module、IM Module 等等,每個單獨的 Business Module 都必須準遵守我們自己的 MVP 架構。

我們在談模塊化的時候,其實就是將業務模塊層的各個功能業務拆分層獨立的業務模塊。所以我們進行模塊化的***步就是業務模塊劃分,但是模塊劃分并沒有一個業界通用的標準,因此劃分的粒度需要根據項目情況進行合理把控,這就需要對業務和項目有較為透徹的理解。拿安居客來舉例,我們會將項目劃分為新房模塊、二手房模塊、IM 模塊等等。

每個業務模塊在 Android Studio 中的都是一個 Module ,因此在命名方面我們要求每個業務模塊都以 Module 為后綴。如下圖所示:

Android模塊化探索與實踐

對于模塊化項目,每個單獨的 Business Module 都可以單獨編譯成 APK。在開發階段需要單獨打包編譯,項目發布的時候又需要它作為項目的一個 Module 來整體編譯打包。簡單的說就是開發時是 Application,發布時是 Library。因此需要在 Business Module 的 build.gradle 中加入如下代碼:

 

  1. if(isBuildModule.toBoolean()){ 
  2.     apply plugin: 'com.android.application' 
  3. }else
  4.     apply plugin: 'com.android.library' 

isBuildModule 在項目根目錄的 gradle.properties 中定義:

 

  1. > isBuildModule=false 

同樣 Manifest.xml 也需要有兩套:

 

  1. sourceSets { 
  2.    main { 
  3.        if (isBuildModule.toBoolean()) { 
  4.            manifest.srcFile 'src/main/debug/AndroidManifest.xml' 
  5.        } else { 
  6.            manifest.srcFile 'src/main/release/AndroidManifest.xml' 
  7.        } 
  8.    } 

如圖:

Android模塊化探索與實踐

debug 模式下的 AndroidManifest.xml :

 

  1. <application 
  2.    ... 
  3.    > 
  4.    <activity 
  5.        android:name="com.baronzhang.android.newhouse.NewHouseMainActivity" 
  6.        android:label="@string/new_house_label_home_page"
  7.        <intent-filter> 
  8.            <action android:name="android.intent.action.MAIN" /> 
  9.            <category android:name="android.intent.category.LAUNCHER" /> 
  10.        </intent-filter> 
  11.    </activity> 
  12. </application> 

realease 模式下的 AndroidManifest.xml :

 

  1. <application 
  2.    ... 
  3.    > 
  4.    <activity 
  5.        android:name="com.baronzhang.android.newhouse.NewHouseMainActivity" 
  6.        android:label="@string/new_house_label_home_page"
  7.        <intent-filter> 
  8.            <category android:name="android.intent.category.DEFAULT" /> 
  9.            <category android:name="android.intent.category.BROWSABLE" /> 
  10.            <action android:name="android.intent.action.VIEW" /> 
  11.            <data android:host="com.baronzhang.android.newhouse" 
  12.                android:scheme="router" /> 
  13.        </intent-filter> 
  14.    </activity> 
  15. </application> 

同時針對模塊化我們也定義了一些自己的游戲規則:

  • 對于 Business Module Layer,各業務模塊之間不允許存在相互依賴關系,它們之間的跳轉通訊采用路由框架 Router 來實現(后面會介紹 Router 框架的實現);
  • 對于 Business Component Layer,單一業務組件只能對應某一項具體的業務,個性化需求對外部提供接口讓調用方定制;
  • 合理控制各組件和各業務模塊的拆分粒度,太小的公有模塊不足以構成單獨組件或者模塊的,我們先放到類似于 CommonBusiness 的組件中,在后期不斷的重構迭代中視情況進行進一步的拆分;
  • 上層的公有業務或者功能模塊可以逐步下放到下層,合理把握好度就好;
  • 各 Layer 間嚴禁反向依賴,橫向依賴關系由各業務 Leader 和技術小組商討決定。

模塊間跳轉通訊(Router)

對業務進行模塊化拆分后,為了使各業務模塊間解耦,因此各個 Bussiness Module 都是獨立的模塊,它們之間是沒有依賴關系。那么各個模塊間的跳轉通訊如何實現呢?

比如業務上要求從新房的列表頁跳轉到二手房的列表頁,那么由于是 NewHouseModule 和 SecondHouseModule 之間并不相互依賴,我們通過想如下這種顯式跳轉的方式來實現 Activity 跳轉顯然是不可能的實現的。

 

  1. Intent intent = new Intent(NewHouseListActivity.this, SecondHouseListActivity.class); 
  2. startActivity(intent); 

有的同學可能會想到用隱式跳轉,通過 Intent 匹配規則來實現:

 

  1. Intent intent = new Intent(Intent.ACTION_VIEW, "://:/");  
  2. startActivity(intent); 

但是這種代碼寫起來比較繁瑣,且容易出錯,出錯也不太容易定位問題。因此一個簡單易用、解放開發的路由框架是必須的了。

Android模塊化探索與實踐

我自己實現的路由框架分為路由(Router) 和參數注入器(Injector) 兩部分:

Android模塊化探索與實踐

Router 提供 Activity 跳轉傳參的功能;Injector 提供參數注入功能,通過編譯時生成代碼的方式在 Activity 獲取獲取傳遞過來的參數,簡化開發。

Router

路由(Router)部分通過 Java 注解結合動態代理來實現,這一點和 Retrofit 的實現原理是一樣的。

首先需要定義我們自己的注解(篇幅有限,這里只列出少部分源碼)。

用于定義跳轉 URI 的注解 FullUri:

 

  1. @Target(ElementType.METHOD) 
  2. @Retention(RetentionPolicy.RUNTIME) 
  3. public @interface FullUri { 
  4.     String value(); 

用于定義跳轉傳參的 UriParam( UriParam 注解的參數用于拼接到 URI 后面):

 

  1. @Target(ElementType.PARAMETER) 
  2. @Retention(RetentionPolicy.RUNTIME) 
  3. public @interface UriParam { 
  4.     String value(); 

用于定義跳轉傳參的 IntentExtrasParam( IntentExtrasParam 注解的參數最終通過 Intent 來傳遞):

 

  1. @Target(ElementType.PARAMETER) 
  2. @Retention(RetentionPolicy.RUNTIME) 
  3. public @interface IntentExtrasParam { 
  4.     String value(); 

然后實現 Router ,內部通過動態代理的方式來實現 Activity 跳轉:

 

  1. public final class Router { 
  2.     ... 
  3.     public <T> T create(final Class<T> service) { 
  4.         return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service}, new InvocationHandler() { 
  5.             @Override 
  6.             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
  7.                 FullUri fullUri = method.getAnnotation(FullUri.class); 
  8.                 StringBuilder urlBuilder = new StringBuilder(); 
  9.                 urlBuilder.append(fullUri.value()); 
  10.                 //獲取注解參數 
  11.                 Annotation[][] parameterAnnotations = method.getParameterAnnotations(); 
  12.                 HashMap<String, Object> serializedParams = new HashMap<>(); 
  13.                 //拼接跳轉 URI 
  14.                 int position = 0; 
  15.                 for (int i = 0; i < parameterAnnotations.length; i++) { 
  16.                     Annotation[] annotations = parameterAnnotations[i]; 
  17.                     if (annotations == null || annotations.length == 0) 
  18.                         break; 
  19.                     Annotation annotation = annotations[0]; 
  20.                     if (annotation instanceof UriParam) { 
  21.                         //拼接 URI 后的參數 
  22.                         ... 
  23.                     } else if (annotation instanceof IntentExtrasParam) { 
  24.                         //Intent 傳參處理 
  25.                         ... 
  26.                     } 
  27.                 } 
  28.                 //執行Activity跳轉操作 
  29.                 performJump(urlBuilder.toString(), serializedParams); 
  30.                 return null
  31.             } 
  32.         }); 
  33.     } 
  34.     ... 

上面是 Router 實現的部分代碼,在使用 Router 來跳轉的時候,首先需要定義一個 Interface(類似于 Retrofit 的使用方式):

 

  1. public interface RouterService {  
  2. @FullUri("router://com.baronzhang.android.router.FourthActivity" 
  3. void startUserActivity(@UriParam("cityName" 
  4. String cityName, @IntentExtrasParam("user"User user);  

接下來我們就可以通過如下方式實現 Activity 的跳轉傳參了:

 

  1. RouterService routerService = new Router(this).create(RouterService.class); 
  2. User user = new User("張三", 17, 165, 88); 
  3. routerService.startUserActivity("上海"user); 

Injector

通過 Router 跳轉到目標 Activity 后,我們需要在目標 Activity 中獲取通過 Intent 傳過來的參數:

 

  1. getIntent().getIntExtra("intParam", 0); 
  2. getIntent().getData().getQueryParameter("preActivity"); 

為了簡化這部分工作,路由框架 Router 中提供了 Injector 模塊在編譯時生成上述代碼。參數注入器(Injector)部分通過 Java 編譯時注解來實現,實現思路和 ButterKnife 這類編譯時注解框架類似。

首先定義我們的參數注解 InjectUriParam :

 

  1. @Target(ElementType.FIELD) 
  2. @Retention(RetentionPolicy.CLASS) 
  3. public @interface InjectUriParam { 
  4.     String value() default ""

然后實現一個注解處理器 InjectProcessor ,在編譯階段生成獲取參數的代碼:

 

  1. @AutoService(Processor.class) 
  2. public class InjectProcessor extends AbstractProcessor { 
  3.     ... 
  4.    @Override 
  5.     public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) { 
  6.         //解析注解 
  7.         Map<TypeElement, TargetClass> targetClassMap = findAndParseTargets(roundEnvironment); 
  8.         //解析完成后,生成的代碼的結構已經有了,它們存在InjectingClass中 
  9.         for (Map.Entry<TypeElement, TargetClass> entry : targetClassMap.entrySet()) { 
  10.             ... 
  11.         } 
  12.         return false
  13.     } 
  14.     ... 

使用方式類似于 ButterKnife ,在 Activity 中我們使用 Inject 來注解一個全局變量:

  1. @Inject User user

然后 onCreate 方法中需要調用 inject(Activity activity) 方法實現注入:

  1. RouterInjector.inject(this); 

這樣我們就可以獲取到前面通過 Router 跳轉的傳參了。

  • 由于篇幅限制,加上為了便于理解,這里只貼出了極少部分 Router 框架的源碼。希望進一步了解 Router 實現原理的可以到 GiuHub 去翻閱源碼,Router 的實現還比較簡陋,后面會進一步完善功能和文檔,之后也會有單獨的文章詳細介紹。源碼地址:https://github.com/BaronZ88/Router

問題及建議

資源名沖突

對于多個 Bussines Module 中資源名沖突的問題,可以通過在 build.gradle 定義前綴的方式解決:

 

  1. defaultConfig { 
  2.    ... 
  3.    resourcePrefix "new_house_" 
  4.    ... 

而對于 Module 中有些資源不想被外部訪問的,我們可以創建 res/values/public.xml,添加到 public.xml 中的 resource 則可被外部訪問,未添加的則視為私有:

  1. <resources> 
  2.     <public name="new_house_settings" type="string"/> 
  3. </resources> 

重復依賴

模塊化的過程中我們常常會遇到重復依賴的問題,如果是通過 aar 依賴, gradle 會自動幫我們找出新版本,而拋棄老版本的重復依賴。如果是以 project 的方式依賴,則在打包的時候會出現重復類。對于這種情況我們可以在 build.gradle 中將 compile 改為 provided,只在最終的項目中 compile 對應的 library ;

其實從前面的安居客模塊化設計圖上能看出來,我們的設計方案能一定程度上規避重復依賴的問題。比如我們所有的第三方庫的依賴都會放到 OpenSoureLibraries 中,其他需要用到相關類庫的項目,只需要依賴 OpenSoureLibraries 就好了。

模塊化過程中的建議

對于大型的商業項目,在重構過程中可能會遇到業務耦合嚴重,難以拆分的問題。我們需要先理清業務,再動手拆分業務模塊。比如可以先在原先的項目中根據業務分包,在一定程度上將各業務解耦后拆分到不同的 package 中。比如之前新房和二手房由于同屬于 app module,因此他們之前是通過隱式的 intent 跳轉的,現在可以先將他們改為通過 Router 來實現跳轉。又比如新房和二手房中公用的模塊可以先下放到 Business Component Layer 或者 Basic Component Layer 中。在這一系列工作完成后再將各個業務拆分成多個 module 。

模塊化重構需要漸進式的展開,不可一觸而就,不要想著將整個項目推翻重寫。線上成熟穩定的業務代碼,是經過了時間和大量用戶考驗的;全部推翻重寫往往費時費力,實際的效果通常也很不理想,各種問題層出不窮得不償失。對于這種項目的模塊化重構,我們需要一點點的改進重構,可以分散到每次的業務迭代中去,逐步淘汰掉陳舊的代碼。

各業務模塊間肯定會有公用的部分,按照我前面的設計圖,公用的部分我們會根據業務相關性下放到業務組件層(Business Component Layer)或者基礎組件層(Common Component Layer)。對于太小的公有模塊不足以構成單獨組件或者模塊的,我們先放到類似于 CommonBusiness 的組件中,在后期不斷的重構迭代中視情況進行進一步的拆分。過程中***主義可以有,切記不可過度。

以上就是我在模塊化探索實踐方面的一些經驗,不住之處還望大家指出。

責任編輯:未麗燕 來源: 碼農網
相關推薦

2025-07-10 03:00:00

2010-02-03 09:01:01

Java動態模塊化

2017-08-08 16:07:57

Android 模塊化架構

2017-08-11 16:10:36

微信Android實踐

2016-12-14 14:50:26

CSS預處理語言模塊化實踐

2019-08-28 16:18:39

JavaScriptJS前端

2021-12-16 22:02:28

webpack原理模塊化

2022-11-02 18:47:46

場景模塊化跨棧

2014-04-27 10:16:31

QCon北京2014Andrew Bett

2017-02-13 18:46:38

Android模塊化組件化

2016-11-08 20:31:19

同方服務器模塊化

2025-05-12 08:45:00

模塊化FastAPI路由分發

2023-08-18 10:49:14

開發攜程

2009-12-10 11:04:08

Java模塊化OSGiJigsaw

2013-08-20 15:31:18

前端模塊化

2020-09-17 10:30:21

前端模塊化組件

2017-05-18 10:23:55

模塊化開發RequireJsJavascript

2022-03-11 13:01:27

前端模塊

2020-09-18 09:02:32

前端模塊化

2015-10-10 11:29:45

Java模塊化系統初探
點贊
收藏

51CTO技術棧公眾號

鬼打鬼之黄金道士1992林正英| 91久久国产最好的精华液| 成人日韩在线电影| 久久精品99国产精| 伊人成综合网伊人222| 欧美中文字幕一区二区三区| 国产四区在线观看| 网站黄在线观看| 久热精品在线| 欧美黑人性生活视频| 白丝女仆被免费网站| 日韩城人网站| 好吊成人免视频| 中文字幕乱码免费| 亚洲黄色在线网站| 性感美女一区二区在线观看| 悠悠色在线精品| 欧美第一黄网| 精品国产av一区二区| 日韩精品亚洲一区二区三区免费| 欧美国产日韩视频| 国产无遮挡在线观看| 精品淫伦v久久水蜜桃| 欧美精品丝袜久久久中文字幕| 久久综合九色综合88i| 欧美成人hd| 久久综合成人精品亚洲另类欧美 | 久久国产精品露脸对白| 久久久亚洲网站| 欧美丰满熟妇bbbbbb| 欧美猛男做受videos| 亚洲精品在线电影| 日本中文字幕在线不卡| 日本午夜精品久久久久| 欧美在线一区二区三区| 99福利在线观看| www.51av欧美视频| 亚洲综合色视频| avove在线观看| 麻豆传媒视频在线观看免费| 日本一区二区视频在线| 任我爽在线视频精品一| 免费在线稳定资源站| 99综合电影在线视频| 国产精品9999久久久久仙踪林| 国产精品一区二区三区在线免费观看 | 成人久久18免费网站麻豆| 亚洲综合在线小说| 国产精品国产一区二区三区四区 | caoporn免费在线视频| 国产精品电影一区二区| 手机成人在线| 国产一级在线观看| 国产亚洲制服色| 日韩成人av电影在线| 天堂中文在线视频| 91视频免费观看| 九九九久久久| 三级视频在线播放| 久久久综合视频| 日韩欧美一区二区三区四区 | 国产日韩欧美不卡在线| 日韩精品久久一区二区三区| 成人p站proumb入口| 欧美激情一区二区三区| 亚洲综合欧美日韩| 大片免费在线观看| 亚洲一区二区三区四区中文字幕| 久艹在线免费观看| segui88久久综合9999| 一本大道久久精品懂色aⅴ | 成人自拍视频网| 欧美日韩亚洲另类| 国产一级片中文字幕| 日韩在线视频一区二区三区| 精品国产1区2区3区| 国产肉体xxxx裸体784大胆| 国产一区二区三区四区大秀| 日韩中文字幕在线播放| 免费一级黄色大片| 国产欧美日韩综合一区在线播放| 国产成人精品久久久| 一级特黄aa大片| 成人h动漫精品| 日本一区美女| 18视频在线观看| 欧美日韩亚洲成人| 另类小说第一页| 亚洲天堂中文字幕在线观看| 亚洲国内高清视频| 四季av中文字幕| 狠狠噜噜久久| 国产精品自拍偷拍| 性一交一乱一色一视频麻豆| 久久久久久免费毛片精品| 大地资源第二页在线观看高清版| 高清电影在线观看免费| 91国内精品野花午夜精品| 99久久99精品| 欧美热在线视频精品999| 久久久999精品| 国产精品人人人人| 国产美女视频一区| 欧美日韩在线一二三| 直接在线观看的三级网址| 色综合久久六月婷婷中文字幕| 网站在线你懂的| 一道在线中文一区二区三区| 美女国内精品自产拍在线播放| 久久亚洲精品国产| 国产精品综合在线视频| 色狠狠久久av五月综合| 欧美裸体视频| 日韩精品在线一区| 毛片视频免费播放| 成人av资源网址| 在线看日韩av| 久久99国产综合精品免费| 国产一区二区三区四| 日韩欧美国产二区| sm捆绑调教国产免费网站在线观看| 777a∨成人精品桃花网| 国产美女永久免费无遮挡| 亚洲青色在线| 99在线看视频| 爆操欧美美女| 欧美日韩国产a| 国产亚洲精品熟女国产成人| 亚洲伦伦在线| 国产精品久久久久av福利动漫| 九色porny丨首页在线| 欧美三级电影网站| 黄色aaa视频| 免费日韩av片| 麻豆视频成人| 色在线中文字幕| 亚洲精品美女在线观看| 欧美人妻一区二区| 国产成人在线视频网站| 国产香蕉一区二区三区| 国产激情一区| 欧美精品免费播放| 国产夫妻性生活视频| 国产大陆精品国产| 最新国产精品久久| 韩国精品视频在线观看| 中文字幕欧美日韩精品| 中文字幕观看视频| 欧美国产日韩在线观看| 欧美 日韩 国产 激情| 欧美男gay| 国产精品色午夜在线观看| 成a人片在线观看www视频| 欧美无乱码久久久免费午夜一区| 欧美黄色高清视频| 日本三级亚洲精品| 一本久道久久综合| 亚洲国产综合在线观看| 久久精品久久久久| 99久久精品国产色欲| 一区2区3区在线看| xfplay5566色资源网站| 一本不卡影院| 欧洲精品亚洲精品| jizz亚洲女人高潮大叫| 久久国产一区二区三区| 精品久久久无码中文字幕| 亚洲国产视频a| 一区二区三区免费在线观看视频 | 91插插插插插插插插| 日本不卡高清| 91久久偷偷做嫩草影院| ririsao久久精品一区| 亚洲欧洲高清在线| 91极品身材尤物theporn| 亚洲色图制服诱惑| 性农村xxxxx小树林| 噜噜噜91成人网| 超碰免费在线公开| 久久婷婷国产| 日韩免费不卡av| 美女黄视频在线观看| 精品国产伦理网| 日韩 国产 欧美| 亚洲欧美二区三区| 国产精品一区二区入口九绯色| 首页欧美精品中文字幕| 蜜臀av.com| 夜夜躁狠狠躁日日躁2021日韩| 国产美女精品免费电影| 男人天堂亚洲天堂| 国产一区二区三区精品久久久| 91在线精品入口| 午夜成人免费电影| 国产又色又爽又高潮免费 | 色天使在线视频| 久久er精品视频| 久久精品视频16| 亚洲天堂一区二区三区四区| 免费国产在线精品一区二区三区| 高清不卡一区| 欧洲中文字幕国产精品| 中文字幕在线观看播放| 国产午夜精品一区理论片飘花 | 国产成人福利片| 久久综合伊人77777麻豆最新章节| 欧美日韩理论| 伊人久久av导航| 国产欧美高清视频在线| 成人在线免费观看一区| 高清亚洲高清| 日韩av免费一区| gratisvideos另类灌满| 日韩有码在线视频| 久久精品色图| 日韩av网站在线| 国产探花精品一区二区| 欧美日韩亚洲国产综合| 天堂网视频在线| 午夜精品福利一区二区三区av| 夫妻性生活毛片| 国产欧美日韩在线| 自拍视频一区二区| 粉嫩绯色av一区二区在线观看 | 91免费国产精品| 天天影视天天精品| 日韩午夜视频在线观看| 小说区图片区色综合区| 国产精品日本一区二区| 精品三级国产| 91在线|亚洲| 久久天天久久| 国产精品亚洲自拍| 高清av一区二区三区| 日韩av电影国产| 成人美女黄网站| 欧美性受xxx| 欧美少妇精品| 欧美专区国产专区| 欧美伦理91| 青青久久av北条麻妃海外网| 看黄在线观看| 2020久久国产精品| 色多多在线观看| 欧美专区中文字幕| 夜鲁夜鲁夜鲁视频在线播放| 欧美亚洲在线播放| 日韩电影免费观| 国产精品99久久久久久久久久久久| 天堂av中文在线观看| 欧洲美女7788成人免费视频| 91av亚洲| 国产精品免费福利| 久久爱.com| 91久久精品国产91久久性色| 亚洲无线观看| 国产在线观看一区| 首页亚洲中字| 日本一区二区久久精品| 97精品国产| 中国黄色录像片| 亚洲美女黄色| 青青青在线播放| 麻豆免费精品视频| 久久精品无码一区二区三区毛片| 国产精品亚洲视频| 老熟妇精品一区二区三区| 久久久亚洲高清| 国产又黄又粗又猛又爽的| 亚洲日本韩国一区| 国产一级特黄a高潮片| 精品久久久久久国产| 亚洲av综合一区| 欧美一区二区在线看| 蜜桃视频污在线观看| 亚洲免费av网址| 好吊日视频在线观看| 久久久久久久久久婷婷| 小h片在线观看| 国产日韩欧美在线看| 都市激情亚洲| 亚洲草草视频| 亚洲无线一线二线三线区别av| 国产精品-区区久久久狼| 蜜桃久久精品一区二区| 亚洲无人区码一码二码三码| 国产拍欧美日韩视频二区| av网页在线| 欧美精品欧美精品系列| 性生交大片免费看女人按摩| 亚洲精品动漫100p| 亚洲s色大片| 97视频在线观看视频免费视频| 日韩精品麻豆| 成人精品一二区| 精品一区二区三| 女人被男人躁得好爽免费视频| 久久一区激情| 人妻 丝袜美腿 中文字幕| 国产三级三级三级精品8ⅰ区| 欧美精品一区二区成人| 欧美视频在线一区二区三区 | 自拍偷拍亚洲一区| gogo久久| 不卡视频一区| 日韩电影免费网址| 女人喷潮完整视频| 国产伦精一区二区三区| 中文字幕免费在线看线人动作大片| 一区二区三区精品在线观看| 岳乳丰满一区二区三区| 日韩精品免费在线视频观看| 三级资源在线| 成人福利网站在线观看| 国产精品一国产精品| 无码熟妇人妻av在线电影| 老司机午夜精品| 少妇大叫太粗太大爽一区二区| 一区二区激情视频| 国产欧美第一页| 色偷偷9999www| 国产成+人+综合+亚洲欧美| 国产精品一区二区a| 亚洲一级毛片| 香蕉视频xxx| 亚洲视频每日更新| 伊人免费在线观看| 亚洲欧美日韩国产中文专区| 天堂√8在线中文| 国产视频一区二区不卡| 国产精品videosex极品| 日韩av影视大全| 成人欧美一区二区三区黑人麻豆| 中文字幕视频免费观看| 国产亚洲一区二区精品| 免费成人动漫| 欧美日韩在线精品| 米奇777在线欧美播放| 国产三级国产精品| 精品日韩中文字幕| 日产精品久久久久久久性色| 91国在线精品国内播放| 老司机精品在线| 黄色国产一级视频| gogogo免费视频观看亚洲一| 日本亚洲色大成网站www久久| 男人天堂资源网| 国产精品福利电影一区二区三区四区 | 99香蕉久久| av在线免费观看国产| 国产成人在线色| 国产特黄大片aaaa毛片| 亚洲精品福利资源站| 色黄视频在线观看| 日本视频一区在线观看| 久久国产三级精品| 97在线观看视频免费| 91精品久久久久久蜜臀| 青青草原av在线| 精品国产日本| 久久国产一二区| gv天堂gv无码男同在线观看 | 天天操天天干天天操| 91精品国产91久久久久| 国产精品视频一区二区三区四蜜臂| 国产一线二线三线在线观看| 中文字幕视频一区| www.av黄色| 欧美在线视频a| 91欧美在线| 少妇高潮一69aⅹ| 欧美视频在线观看 亚洲欧| 国产一级在线| 91超碰在线免费观看| 亚洲精品女人| 日本精品久久久久中文| 欧美一区二区三区在线视频| 国产白丝在线观看| 日韩欧美在线电影| 国产成人在线视频网站| 亚洲天堂一区在线| 日韩少妇与小伙激情| 综合成人在线| 人人干人人视频| 亚洲永久精品国产| 蝌蚪视频在线播放| 亚洲在线观看视频网站| 亚洲欧美日韩国产综合精品二区| 久久久久久久久久97| 亚洲成人精品久久久| 国产精品久久久久77777丨| 国内少妇毛片视频| 亚洲国产精品ⅴa在线观看| 亚洲大尺度视频| 国产精品尤物福利片在线观看| 欧美亚洲不卡| 91免费在线看片| 日韩精品视频在线观看免费| 成人免费观看49www在线观看| 99福利在线观看|