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

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

從 View 繪制談性能優化

2019-11-07 23:04:11
字體:
來源:轉載
供稿:網友

轉載請注明出處:http://blog.csdn.net/wl9739/article/details/57416433

在開發過程中,往往會聽到 “性能優化” 這個概念,這個概念很大,比如網絡性能優化、耗電量優化等等,對我們開發者而言,最容易做的,或者是影響最大的,應該是 View 的性能優化。一般小項目或許用不上 View 性能優化,然而,當業務愈加龐大、界面愈加復雜的時候,沒有一個良好的開發習慣和 View 布局優化常識,做出來的界面很容易出現 “卡頓” 現象,從而嚴重影響用戶體驗。而對于我們開發者來說,了解一些 View 性能優化的常識,增強開發技巧,可以說是一門必備的功課。

為了更好地理解 View 性能優化的原理,以及造成 “卡頓” 的可能原因,我們從 View 的繪制流程開始討論。之后,會介紹一些寫界面布局常用的一些標簽及使用注意事項。

View 繪制流程

我們都知道,View 的繪制分為三個階段:測量、布局和繪制,這三個階段各自的作用如下:

measure: 為整個 View 樹計算實際的大小,即設置實際的高(對應屬性:mMeasureHeight)和寬(對應屬性:mMeasureWidth),每個 View 的控件的實際寬高都是由父視圖和本身視圖所決定的。layout:為將整個根據子視圖的大小以及布局參數將 View 樹放到合適的位置上。draw:利用前兩部得到的參數,將視圖顯示在屏幕上。

當一個 Activity 對象被創建完成之后,會將一個 DecorView 對象添加到 Window 中,同時會創建一個 ViewRootImpl 對象,并將 ViewRootImpl 對象和 DecorView 對象建立聯系,然后繪制流程就會從 ViewGroup 的 performTraversals() 方法開始執行,如下圖所示:

View 繪制流程

整個繪制流程從 ViewRootImpl 的 performTraversals() 方法開始,在該方法內會調用 performMeasure() 方法進行測量子 View(也就是根 View,頂級的 ViewGroup)。然后在 performMeasure 中會調用 measure() 方法來執行具體的測量邏輯,這個時候,代碼邏輯就從 ViewRootImp 跳轉到了 View 類中了:

PRivate void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure"); try { mView.measure(childWidthMeasureSpec, childHeightMeasureSpec); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); }}

measure() 方法中,有一個 onMeasure() 方法,用于這個方法用來測量子元素的大小,也將測量流程從父元素傳遞到子元素當中去。緊接著子元素會重復父元素的測量流程,如此反復,就完成了一顆 View 樹的遍歷。當 measure() 方法完成后,會將結果存儲在 LongSparseLongArray 類型的變量 mMeasureCache 中。

performTraversals() 方法中,調用完 performMeasure(),后,會接著調用 performLayout()performDraw() 進行 View 的布局和繪制。這兩個流程和測量的流程差不多,就不再敘述。

而這三個階段分別作了什么呢?源碼太長就不貼了,主要的作用如下:

Measure 過程

設置本 View 視圖的最終大小。如果該 View 對象是個 ViewGroup 類型,需要重寫該 onMeasure() 方法,對其子視圖進行遍歷 measure() 過程。 measureChildren(),內部使用了一個 for 循環對子視圖進行遍歷,分別調用了子視圖的 measure() 方法。measureChild(),為指定的子視圖 measure,會被 measureChildren 調用。measureChildWidthMargins(),為指定的子視圖考慮了 margin 和 padding 的 measure。

Layout 過程

layout() 方法會設置該 View 視圖位于父視圖的坐標軸,即 mLeft, mTop, mRight, mBottom.(調用 setFrame() 方法去實現),接下來回調 onLayout() 方法(如果該 View 是 ViewGroup 對象,需要實現該方法,對每個視圖進行布局);如果該 View 是個 ViewGroup 類型,需要遍歷每個子視圖 childView。調用該子視圖的 layout() 方法去設置它的坐標值。

Draw 過程

繪制背景如果要視圖顯示漸變框,這里會做一些準備工作繪制視圖本身,即調用 onDraw() 方法。在 view 中,onDraw() 是個空方法,也就是說具體的視圖都啊喲覆蓋該方法來實現自己的顯示(比如 TextView 在這里實現了繪制文字的過程)。而對于 ViewGroup 則不需要實現該方法,因為作為容器是沒有內容的,其包含了多個子 View,而子 View 已經實現了自己的繪制方法,因此只需要告訴子 View 繪制自己就行了,也就是下面的 dispatchDraw() 方法。繪制視圖,即 dispatchDraw() 方法。在 View 中這是個空方法,具體的視圖不需要實現該方法,它是專門為容器類準備的,也就是容器必須實現該方法。如果需要,開始繪制漸變框。繪制滾動條。

因此,如果我們去掉不必要的背景,去掉漸變框,去掉滾動條,在一定程度上是能加快繪制速度的。

優化

幀率(frame per second,即 FPS),指的是每秒刷新的次數。一般電影的幀率為 24FPS、25FPS 和 30FPS。而游戲的幀率一般要保持 60FPS 才能叫做流暢,當游戲的 FPS 低于 30 時,我們就會感受到明顯地卡頓。Android 系統每隔 16ms 觸發一次 UI 刷新操作,這就要求我們的應用都能在 16ms 內繪制完成。如果有一次的界面繪制用了 22ms,那么,用戶在 32ms 內看見的都是同一個界面。情況嚴重的就會讓用戶感受到應用運行”卡頓“。

因此,優化的目的,主要就是減少繪制時間,盡量保證每個界面都能在 16ms 內完成繪制。而優化的方案,從上面的分析,我們可以分兩個方面:

如何優化

從內優化

減少 View 層級。這樣會加快 View 的循環遍歷過程。去除不必要的背景。由于 在 draw 的步驟中,會單獨繪制背景。因此去除不必要的背景會加快 View 的繪制。盡可能少的使用 margin、padding。在測量和布局的過程中,對有 margin 和 padding 的 View 會進行單獨的處理步驟,這樣會花費時間。我們可以在父 View 中設置 margin 和 padding,從而避免在子 View 中每個單獨設置和配置。去除不必要的 scrollbar。這樣能減少 draw 的流程。慎用漸變。能減少 draw 的流程。

從外優化

布局嵌套過于復雜。這會直接 View 的層級變多。View 的過渡繪制。View 的頻繁重新渲染。UI 線程中進行耗時操作。在 Android 4.0 之后,不允許在 UI 線程做網絡操作。冗余資源及錯誤邏輯導致加載和執行緩慢。簡單的說,就是代碼寫的爛。頻繁觸發 GC,導致渲染受阻。當系統在短時間內有大量對象銷毀,會造成內存抖動,頻繁觸發 GC 線程,而 GC 線程的優先級高于 UI 線程,因而會造成渲染受阻。

外部因素最為致命!日常開發中更多的應該關心布局的嵌套層級和冗余資源。

比如,當需要將一個 TextView 和一張圖片放在一起展示時,我們可以考慮使用 TextView 的 drawableLeft(drawableRight、drawableTop、drawableBottom) 屬性來設置圖片,而不是使用一個 LinearLayout 來將 TextView 和 ImageView 封裝在一起,這樣就能減少 View 的繪制層級。

又比如,子元素和父元素都是相同的背景時,就不必在每個子元素中都添加背景屬性,等等。

線性布局和相對布局

線性布局和相對布局是我們平時使用最多的布局方式。在一般開發場景中,兩者的渲染效率沒有明顯差別,但是如果真要較真的話,他們之間還是有細微差別的。

RelativeLayout 在測量子 View 排列方式是基于彼此的依賴關系,這種依賴關系導致了子 View 的顯示順序不一定和布局中的 View 的順序相同,在確定所有子 View 的時候,會先對所有的 View 進行排序,同時,由于 RelativeLayout 允許 “A在橫向上依賴于 B,B 在縱向上依賴于 A“,因此會測量兩次,導致測量效率較低。而 LinearLayout 由于有 orientation 屬性,則測量就很簡單了。

LinearLayout 在設置 weight 屬性的時候,也會導致二次測量:首先會遍歷測量沒有 weight 屬性的 View,然后再遍歷測量包含 weight 屬性的 View。

布局比較

布局比較

選擇布局容器的基本準則:

盡可能的使用 RelativeLayout 以減少 View 層級,使 View 樹趨于扁平化。在不影響層級深度的情況下,使用 LinearLayout 和 FrameLayout 而不是 RelativeLayout。

布局標簽

說到布局標簽,我想大概很多人都用過一些。為了說明 Android 系統對于這些標簽的處理,我們先看一下 xml 布局是如何解析繪制到屏幕的。

在 Activity 的 onCreate() 方法中,我們一般會調用 setContentView() 方法,這個方法負責將 XML 文件解析繪制到屏幕上,這個方法很簡單:

public void setContentView(@LayoutRes int layoutResID) { getWindow().setContentView(layoutResID); initWindowDecorActionBar();}

這個方法第一行是調用 Window 類的 setContentView(),第二行是初始化 ActionBar。Window 類是一個抽象類,它是所有視圖相關類的頂層類,其唯一一個實現類是 PhoneWindow,在 PhoneWindow 類的 setContentView() 方法中,會先移除掉所有的 view 視圖,然后再調用 LayoutInflater.inflate() 方法繪制,在 LayoutInflater 的 inflate() 方法中,會創建一個 XmlResourceParser 解析器,然后再進行解析。我們來看看 inflate() 方法里面干了什么:

public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) { View result = root; ...... final String name = parser.getName(); // 這里的 TAG_MERGE 其實就是 merge 標簽 if (TAG_MERGE.equals(name)) { if (root == null || !attachToRoot) { throw new InflateException("<merge /> can be used only with a valid " + "ViewGroup root and attachToRoot=true"); } rInflate(parser, root, inflaterContext, attrs, false); } else { // 這里的 createViewFromTag() 方法創建的是根布局 final View temp = createViewFromTag(root, name, inflaterContext, attrs); ...... ViewGroup.LayoutParams params = null; if (root != null) { // 根據 xml 屬性生成布局參數 params = root.generateLayoutParams(attrs); // 生成子元素的布局 rInflateChildren(parser, temp, attrs, true); if (root != null && attachToRoot) { root.addView(temp, params); } ...... } ...... } return result;}

為了方便閱讀,我將一些代碼省略掉,從上面可以看出大致的解析流程:先判斷是否有 merge 標簽,然后檢查其合理性,注意源碼已經說明了,merge 標簽只能用在 ViewGroup 的根布局中,并且 attachToRoot 必須要設置為 true。然后調用 rInflate() 方法;如果沒有 merge 標簽,就會調用 rInflateChildren() 方法生成子元素的布局,而這個 rInflateChildren() 方法最終也是輾轉到前面的 rInflate() 方法中,我們來看一下這個方法:

void rInflate(XmlPullParser parser, View parent, Context context, AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException { final int depth = parser.getDepth(); int type; while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) { if (type != XmlPullParser.START_TAG) { continue; } final String name = parser.getName(); // 判斷是否有標簽 requestFocus if (TAG_REQUEST_FOCUS.equals(name)) { // parseRequestFocus() 方法里面其實就是 parent.requestFocus() 方法!就這么簡單! parseRequestFocus(parser, parent); } // 判斷是否有標簽 tag else if (TAG_TAG.equals(name)) { parseViewTag(parser, parent, attrs); } // 判斷是否有標簽 include,該標簽不能用在根元素中。 else if (TAG_INCLUDE.equals(name)) { if (parser.getDepth() == 0) { throw new InflateException("<include /> cannot be the root element"); } parseInclude(parser, context, parent, attrs); } // 判斷是否有標簽 merge,該標簽只能用在根元素中。由于這里是處理 View 元素的布局,因此直接拋異常 else if (TAG_MERGE.equals(name)) { throw new InflateException("<merge /> must be the root element"); } else { // 這里的 createViewFromTag() 方法會根據 View 標簽創建 View 對象。 final View view = createViewFromTag(parent, name, context, attrs); final ViewGroup viewGroup = (ViewGroup) parent; final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs); rInflateChildren(parser, view, attrs, true); viewGroup.addView(view, params); } } if (finishInflate) { parent.onFinishInflate(); }}

這里面一共涉及到了四個標簽:<requestFocus/>,<tag/><include/><merge/>。下面來分別說一下:

requestFocus

requestFocus 標簽就是讓標簽內的 View 獲取焦點,其內部就是使用 view.requestFocus() 方法實現的。

tag

tag 標簽是 API 21 里面新增的,用來給 View 對象添加額外的信息。從 Android 1.0 開始,Android 就開始支持給 View 對象調用 setTag(Object) 和 getTag(Object) 來添加和獲取標簽信息,到了 Android 1.6 ,添加和獲取標簽信息有了新的方法:setTag(int, Object)。而在 Android 4.0 之后,setTag(int, Object) 的內部實現改為非靜態的 SparseArray 來實現。Android 5.0 的時候,提供了一種全新的寫法,就是 tag 標簽。

舉一個例子來說明這個標簽怎么用,先編寫一個 XML 布局文件:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/btn_negative" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="cancel"> <tag android:id="@+id/btn_state_negative" android:value="@string/btn_state_negative" /> </Button> <Button android:id="@+id/btn_positive" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="ok"> <tag android:id="@+id/btn_state_positive" android:value="@string/btn_state_positive" /> </Button></LinearLayout>

然后我們就可以通過下面的方式獲取標簽信息:

Button btn_negative = (Button) findViewById(R.id.btn_negative);String tag = (String) btn_negative.getTag(R.id.btn_state_negative);

tag 標簽是這四個標簽中唯一一個需要指定 id 屬性的!

include

我們來看看 處理 include 標簽的方法 parseInclude() 里面的邏輯:

private void parseInclude(XmlPullParser parser, Context context, View parent, AttributeSet attrs) throws XmlPullParserException, IOException { // ATTR_LAYOUT 即 layout 屬性, int layout = attrs.getAttributeResourceValue(null, ATTR_LAYOUT, 0); ...... // 使用了 include 標簽而沒有為其設置 layout 屬性,是會拋異常的! if (layout == 0) { final String value = attrs.getAttributeValue(null, ATTR_LAYOUT); throw new InflateException("You must specify a valid layout " + "reference. The layout ID " + value + " is not valid."); } else { ...... final String childName = childParser.getName(); if (TAG_MERGE.equals(childName)) { // The <merge> tag doesn't support android:theme, so // nothing special to do here. rInflate(childParser, parent, context, childAttrs, false); } else { // createViewFromTag() 方法采用反射的方式,根據標簽名創建一個 view 對象 // 注意這里的標簽并不包括之前提到的 merge 和 include 等等,而是指的 Button、TextView 等 View 相關標簽。 final View view = createViewFromTag(parent, childName, context, childAttrs, hasThemeOverride); ViewGroup.LayoutParams params = null; try { params = group.generateLayoutParams(attrs); } catch (RuntimeException e) { // Ignore, just fail over to child attrs. } if (params == null) { params = group.generateLayoutParams(childAttrs); } view.setLayoutParams(params); // Inflate all children. rInflateChildren(childParser, view, childAttrs, true); // 設置 View 對象的 id 屬性 if (id != View.NO_ID) { view.setId(id); } // 設置 View 對象的可見性 switch (visibility) { case 0: view.setVisibility(View.VISIBLE); break; case 1: view.setVisibility(View.INVISIBLE); break; case 2: view.setVisibility(View.GONE); break; } group.addView(view); } } ...... LayoutInflater.consumeChildElements(parser);}

parseInclude() 方法里面會判斷是否需要處理 merge 標簽,然后根據標簽名(如 Button、TextView 等)調用 createViewFromTag() 方法創建一個 view 對象,然后生成該對象的布局參數,設置 id 屬性,設置可見性等等。

然后注意到 createViewFromTag(),顧名思義,該方法會根據 XML 的標簽來創建 View 對象,這個方法里面最終會調用到 createView() 方法,是使用反射來創建 View 對象的具體實現。

有個問題不知道大家注意到沒有,這些 id、可見性等等的屬性都是 view 對象的,而 include 標簽和 merge 標簽并并沒有這些屬性,也就是說,如果你在 include 或 merge 標簽中設置了一個 id,然后在代碼中通過 findViewById() 方法企圖找到這個 include 或 merge 的布局,是會報空指針異常的!

我這里為了方便區分,將 include、merge 等標簽稱為“布局標簽”,它們不能創建為 View 對象,設置 id 屬性對它們沒有意義。而將 XML 中的 Button、TextView 等標簽稱為“視圖標簽”(視圖元素、控件等),因為它們能被創建為 View 對象,可以設置 id 等熟悉。

其他比較有趣的標簽

除了上面介紹的 merge、include、requestFocus 和 tag 等布局標簽外,還有如下常用的 View 標簽:

ViewStub

利用 ViewStub 標簽可以讓布局懶加載。當你界面要顯示很多內容,而其中一些不用立即顯示出來的時候(比如商品詳情、下載進度條等等),可以使用 ViewStub 標簽,讓 ViewStub 引用這些不用立馬加載的界面布局,當需要的時候再讓它們加載出來。ViewStub 雖然是 View 標簽,但是其本身沒有大小,不會繪制任何東西,因此是一個非常輕量的 View 標簽。

使用 ViewStub 和 include 標簽類似,需要使用 android:layout 屬性來確定哪些布局需要懶加載,同時,由于 ViewStub 是一個 View 標簽,因此需要使用一個 id 來操作 ViewStub。比如使用 ViewStub 簡單的 XML 如下:

<ViewStub android:id="@+id/stab_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout="@layout/text_view" />

java 代碼中,對 ViewStub 的操作有兩種方式:

設置 View 的可見性

findViewById(R.id.stab_view)).setVisibility(View.VISIBLE);

調用 ViewStub 的 inflate() 方法

ViewStub stubView = (ViewStub) findViewById(R.id.stab_view);stubView.inflate();

上面兩種方法都可以加載由 ViewStub 引用的布局。使用 ViewStub 有兩點需要注意:

當調用了 inflate() 方法后,ViewStub 標簽就從視圖中移除了,也就是說,inflate() 方法不能對同一個 ViewStub 調用兩次。ViewStub 所引用的布局的根標簽不能為 標簽。

Space

這是是一個空控件,該 View 沒有實現 onDraw() 方法,因此繪制效率比較高。該控件可以用來占用空白(比如代替 padding 和 margin)。

大概差不多了,View 的性能優化還有一些沒有介紹,比如 Overdraw 等,這里就給個鏈接吧:OverDraw

同時,對于 View 性能優化有興趣的同學,歡迎參加視頻課程:有心課堂


上一篇:as筆記3

下一篇:CSS樣式設置小技巧

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美激情一区二区久久久| 中文字幕自拍vr一区二区三区| 日产精品久久久一区二区福利| 欧美一级在线播放| 国产精品入口免费视| 欧美激情a在线| 欧美日韩国产91| 成人欧美在线观看| 欧美激情精品久久久久久大尺度| 88国产精品欧美一区二区三区| 国产成人一区三区| 亚洲精品自拍第一页| 亚洲精品自产拍| 亚洲一区二区在线播放| 国产欧美日韩中文字幕| 亚洲精品美女在线观看播放| 亚洲第一免费网站| 亚洲国产精品va在线看黑人动漫| 国产精品久久久久999| 欧美在线日韩在线| 国产精品丝袜久久久久久高清| 992tv成人免费视频| 成人在线小视频| 26uuu亚洲国产精品| 亚洲欧美激情一区| 亚洲综合中文字幕在线| 国产视频在线观看一区二区| 亚洲成人久久网| 欧美精品生活片| 日韩欧美亚洲范冰冰与中字| 国产精品久久久久久久久粉嫩av| 欧洲美女7788成人免费视频| 日本成人精品在线| 国产区精品在线观看| 久久香蕉频线观| 神马久久桃色视频| 成人高清视频观看www| 欧美在线观看日本一区| 亚洲国产精品系列| 久久在精品线影院精品国产| 欧美日在线观看| 在线成人中文字幕| xxxxxxxxx欧美| 久久夜色精品亚洲噜噜国产mv| 一二美女精品欧洲| 欧美亚洲另类制服自拍| 日韩中文在线中文网在线观看| 激情懂色av一区av二区av| 一本色道久久综合亚洲精品小说| 亚洲一区二区免费| 久久精品99国产精品酒店日本| 精品中文字幕乱| 久久久久久久一| 欧美国产日韩一区二区| 精品久久久久久久久久久久久久| 国产91精品久久久久久| 国产精品日韩在线| 国产免费一区视频观看免费| 午夜精品久久久久久久99热浪潮| 97精品伊人久久久大香线蕉| 这里精品视频免费| 4k岛国日韩精品**专区| 精品一区二区三区电影| 国产偷国产偷亚洲清高网站| 国产欧美一区二区三区四区| 热99精品里视频精品| 欧美日韩中文字幕日韩欧美| 久久视频在线视频| 亚洲人成在线观| 日韩欧美中文字幕在线观看| 精品久久久久久中文字幕| 美乳少妇欧美精品| 91精品国产综合久久久久久蜜臀| 亚洲最大福利网| 欧美视频在线免费看| 欧美激情一区二区三级高清视频| 国产在线精品一区免费香蕉| 久久久91精品国产| 在线观看国产精品日韩av| 2020欧美日韩在线视频| 日韩精品极品在线观看播放免费视频| 中文字幕日韩视频| 国产91亚洲精品| 一区二区三区在线播放欧美| 久久国产精品久久久久久久久久| 国产精品久久久久久久久久三级| 国产精品亚洲网站| 欧美猛男性生活免费| 在线观看精品国产视频| 亚洲理论片在线观看| 在线观看中文字幕亚洲| 久久精品精品电影网| 欧美一级视频免费在线观看| 美日韩在线视频| 欧美在线影院在线视频| 国外日韩电影在线观看| 国产成人精品av在线| 日韩精品电影网| 久久亚洲电影天堂| 日韩视频免费中文字幕| 成人乱人伦精品视频在线观看| 大胆欧美人体视频| 最近中文字幕mv在线一区二区三区四区| 国产精品久久久久久亚洲调教| 伦理中文字幕亚洲| 国产999在线观看| 精品亚洲va在线va天堂资源站| 日韩av在线免费看| 国产精品久在线观看| 国产精品久久激情| 国产日韩欧美夫妻视频在线观看| 韩日精品中文字幕| 欧美午夜激情视频| 成人xvideos免费视频| 日韩女优人人人人射在线视频| 在线播放国产一区中文字幕剧情欧美| 亚洲xxxx视频| 久久激情五月丁香伊人| 久久久久久噜噜噜久久久精品| 精品久久久久久中文字幕大豆网| 狠狠干狠狠久久| 亚洲欧美精品中文字幕在线| 日本电影亚洲天堂| 亚洲综合大片69999| 久热99视频在线观看| 国产精品自产拍在线观看| 中文字幕av一区二区| 日韩av免费在线看| 日韩在线视频线视频免费网站| 久久97久久97精品免视看| 日韩欧美主播在线| 日韩精品视频免费专区在线播放| 亚洲欧美日韩在线一区| 国产精品青青在线观看爽香蕉| 自拍偷拍亚洲在线| 亚洲精品720p| 91精品国产91久久久久久| 欧美日韩高清在线观看| 久久人人97超碰精品888| 最近的2019中文字幕免费一页| 欧美特黄级在线| 另类色图亚洲色图| 欧美精品免费在线观看| 欧美成人第一页| 中文在线资源观看视频网站免费不卡| 久久久久久国产精品三级玉女聊斋| 精品亚洲国产视频| 欧美中文字幕第一页| 姬川优奈aav一区二区| 亚洲成**性毛茸茸| 亚洲国产精品久久久| 亚洲欧美日韩天堂一区二区| 国产精品羞羞答答| 深夜精品寂寞黄网站在线观看| 日韩性xxxx爱| 国产精品成熟老女人| 美女精品久久久| 国产精品极品尤物在线观看| 91精品国产网站| 亚洲精品国产suv| 中文字幕av一区| 国产69精品久久久久久| 国产成人福利夜色影视| 成人精品久久av网站|