3atv精品不卡视频,97人人超碰国产精品最新,中文字幕av一区二区三区人妻少妇,久久久精品波多野结衣,日韩一区二区三区精品

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android Loader机制全面详解及源码浅析

發布時間:2025/4/16 Android 62 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android Loader机制全面详解及源码浅析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文出處:csdn@工匠若水,http://blog.csdn.net/yanbober/article/details/48861457

一、概述

在Android中任何耗時的操作都不能放在UI主線程中,所以耗時的操作都需要使用異步實現。同樣的,在ContentProvider中也可能存在耗時操作,這時也該使用異步操作,而3.0之后最推薦的異步操作就是Loader。它可以方便我們在Activity和Fragment中異步加載數據,而不是用線程或AsyncTask,他的優點如下:

  • 提供異步加載數據機制;
  • 對數據源變化進行監聽,實時更新數據;
  • 在Activity配置發生變化(如橫豎屏切換)時不用重復加載數據;
  • 適用于任何Activity和Fragment;

注意:由于在我們現在的多個項目中都大量的使用了Loader來處理數據加載(而且由于粗心跳過幾個坑,譬如Loader ID重復導致數據邏輯異常、多線程中restartLoader導致Loader拋出異常(最后保證都在UI線程中執行即可)等),所以接下來我們進行下使用及源碼淺析。

PPPS:前方高能,文章巨長,請做好心理準備(您可以選擇通過左上角目錄點擊索引到感興趣的章節直接查看,或者,或者,或者直接高能往下看)。

二、基礎使用實例

該基礎實例講解完全來自于官方文檔,詳細可以點擊我查看英文原文。

既然接下來準備要說說他的使用強大之處了,那不妨我們先來一張圖直觀的感性認識下不用Loader(左)與用Loader(右)對我們開發者及代碼復雜度和框架的影響吧,如下:

Loader API概述說明

如下是我們開發中常用的一些Loader相關接口:

Class/InterfaceDescription
LoaderManager一個與Activity、Fragment關聯的抽象類,用于管理一個或多個Loader實例。每個Activity或Fragment只能有一個LoaderManager,而一個LoaderManager可以有多個Loader。
LoaderManager.LoaderCallbacks用于和LoaderManager交互的回調接口。譬如,可以使用onCreateLoader()創建一個新的Loader。
AsyncTaskLoader抽象的Loader,提供一個AsyncTask繼承實現。
CursorLoaderAsyncTaskLoader的子類,用于向ContentResover請求返回一個Cursor。該類以標準游標查詢實現了Loader協議,使用后臺線程進行查詢,使用這個Loader是從ContentProvider加載異步數據最好的方式。

在應用中使用Loader

在我們開發的一個App里,使用Loader時常規的步驟包含如下一些操作需求:

  • 一個Activity或Fragment;
  • 一個LoaderManager實例;
  • 一個CursorLoader,從ContentProvider加載數據;
  • 一個LoaderManager.LoaderCallbacks實現,創建新Loader及管理已存在Loader;
  • 一個組織Loader數據的Adapter,如SimpleCursorAdapter;

下面我們看下具體流程。

啟動一個Loader(initLoader)

一個Activity或Fragment中LoaderManager管理一個或多個Loader實例,每個Activity或Fragment只有一個LoaderManager,我們可以在Activity的onCreate()或Fragment的onActivityCreated()里初始化一個Loader。例如:

// Prepare the loader. Either re-connect with an existing one, // or start a new one. getLoaderManager().initLoader(0, null, this);

可以看見上面的initLoader()方法有三個參數:

  • 第一個參數代表當前Loader的ID;
  • 第二個參數代表提供給Loader構造函數的參數,可選;
  • 第三個參數代表LoaderManager.LoaderCallbacks的回調實現;

上面initLoader()方法的調用確保了一個Loader被初始化和激活的狀態,該方法的調運有如下兩種結果:

  • 如果代表該Loader的ID已經存在,則后面創建的Loader將直接復用已經存在的;
  • 如果代表該Loader的ID不存在,initLoader()會觸發LoaderManager.LoaderCallbacks回調的onCreateLoader()方法創建一個Loader;

可以看見通過initLoader()方法可以將LoaderManager.LoaderCallbacks實例與Loader進行關聯,且當Loader的狀態變化時就被回調。所以說,如果調用者正處于其開始狀態并且被請求的Loader已經存在,且已產生了數據,那么系統會立即調用onLoadFinished()(在initLoader()調用期間),所以你必須考慮到這種情況的發生。

當然了,intiLoader()會返回一個創建的Loader,但是你不用獲取它的引用,因為LoadeManager會自動管理該Loader的生命周期,你只用在它回調提供的生命周期方法中做自己數據邏輯的處理即可。

重啟一個Loader(restartLoader)

通過上面initLoader()方法介紹我們可以知道initLoader調運后要么得到一個ID已存在的Loader,要么創建一個新的Loader;但是有時我們想丟棄舊數據然后重新開始創建一個新Loader,這可怎么辦呢?別擔心,要丟棄舊數據調用restartLoader()即可。例如,SearchView.OnQueryTextListener的實現重啟了Loader,當用戶查詢發生變化時Loader需要重啟,如下:

public boolean onQueryTextChanged(String newText) {// Called when the action bar search text has changed. Update// the search filter, and restart the loader to do a new query// with this filter.mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;getLoaderManager().restartLoader(0, null, this);return true; }

上面方法的參數啥的和再上面的init方法類似,就不再羅嗦了。

使用LoaderManager Callbacks

LoaderManager.LoaderCallbacks是LoaderManager的回調交互接口。LoaderManager.LoaderCallbacks包含如下三個方法:

  • onCreateLoader()
    實例化并返回一個新創建給定ID的Loader對象;
  • onLoadFinished()
    當創建好的Loader完成了數據的load之后回調此方法;
  • onLoaderReset()
    當創建好的Loader被reset時調用此方法,這樣保證它的數據無效;

onCreateLoader說明

當你嘗試使用一個Loader(譬如通過initLoader()方法),它會檢查給定Loader的ID是否存在,如果不存在就觸發LoaderManager.LoaderCallbacks里的onCreateLoader()方法創建一個新Loader。創建新Loader實例典型的做法就是通過CursorLoader類創建,不過你也可以自定義一個繼承自Loader的子類來實現自己的Loader。

下面的例子中我們通過onCreateLoader()回調創建一個CursorLoader實例,使用CursorLoader的構造方法創建實例時需要一些參數去查詢一個ContentProvider。具體參數如下:

參數說明
uri準備獲取內容的URI
projection要返回的列key list,null表示返回所有列,但是返回所有列很多時候會降低性能
selection要返回的行過濾,也就是SQL中的WHERE語句,null代表返回uri指定的所有行
selectionArgs用來替換上面selection中包含的"?"
sortOrder結果的行排序,也就是SQL中的ORDER BY,傳遞null則無序

.

// If non-null, this is the current filter the user has provided. String mCurFilter; ... public Loader<Cursor> onCreateLoader(int id, Bundle args) {// This is called when a new Loader needs to be created. This// sample only has one Loader, so we don't care about the ID.// First, pick the base URI to use depending on whether we are// currently filtering.Uri baseUri;if (mCurFilter != null) {baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,Uri.encode(mCurFilter));} else {baseUri = Contacts.CONTENT_URI;}// Now create and return a CursorLoader that will take care of// creating a Cursor for the data being displayed.String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("+ Contacts.HAS_PHONE_NUMBER + "=1) AND ("+ Contacts.DISPLAY_NAME + " != '' ))";return new CursorLoader(getActivity(), baseUri,CONTACTS_SUMMARY_PROJECTION, select, null,Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); }

onLoadFinished說明

當創建好的Loader完成數據加載時回調此方法,我們要確保該方法在Loader釋放現有維持的數據之前被調用。在這里我們應該移除所有對舊數據的使用(因為舊數據不久就會被釋放),但是不用釋放舊數據,因為Loader會幫我們完成舊數據的釋放。

Loader一旦知道App不再使用舊數據就會釋放掉。例如,如果數據來自CursorLoader里的一個Cursor,我們不應該自己在代碼中調用close()方法;如果一個Cursor正在被放置到一個CursorAdapter時我們應當使用swapCursor()進行新數據交換,這樣正在被放置的舊的Cursor就不會被關掉,也就不會導致Adapter的加載異常。

// This is the Adapter being used to display the list's data. SimpleCursorAdapter mAdapter; ...public void onLoadFinished(Loader<Cursor> loader, Cursor data) {// Swap the new cursor in. (The framework will take care of closing the// old cursor once we return.)mAdapter.swapCursor(data); }

onLoaderReset說明

當實例化好的Loader被重啟時該方法被回調,這里會讓Loader的數據置于無效狀態。這個回調方法其實就是為了告訴我們啥時候數據要被釋放掉,所以我們應該在這個時候移除對它的引用。如下移除實例:

// This is the Adapter being used to display the list's data. SimpleCursorAdapter mAdapter; ...public void onLoaderReset(Loader<Cursor> loader) {// This is called when the last Cursor provided to onLoadFinished()// above is about to be closed. We need to make sure we are no// longer using it.mAdapter.swapCursor(null); }

Loader使用實例實戰

下面這個實例是一個Fragment,模擬的是用ListView顯示通訊錄的實時匹配查詢結果,使用CursorLoader管理通訊錄Provider查詢。如下源碼,比較簡單,注釋也很豐富了,所以不過多解釋:

public static class CursorLoaderListFragment extends ListFragmentimplements OnQueryTextListener, LoaderManager.LoaderCallbacks<Cursor> {// This is the Adapter being used to display the list's data.SimpleCursorAdapter mAdapter;// If non-null, this is the current filter the user has provided.String mCurFilter;@Override public void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);// Give some text to display if there is no data. In a real// application this would come from a resource.setEmptyText("No phone numbers");// We have a menu item to show in action bar.setHasOptionsMenu(true);// Create an empty adapter we will use to display the loaded data.mAdapter = new SimpleCursorAdapter(getActivity(),android.R.layout.simple_list_item_2, null,new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },new int[] { android.R.id.text1, android.R.id.text2 }, 0);setListAdapter(mAdapter);// Prepare the loader. Either re-connect with an existing one,// or start a new one.getLoaderManager().initLoader(0, null, this);}@Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {// Place an action bar item for searching.MenuItem item = menu.add("Search");item.setIcon(android.R.drawable.ic_menu_search);item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);SearchView sv = new SearchView(getActivity());sv.setOnQueryTextListener(this);item.setActionView(sv);}public boolean onQueryTextChange(String newText) {// Called when the action bar search text has changed. Update// the search filter, and restart the loader to do a new query// with this filter.mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;getLoaderManager().restartLoader(0, null, this);return true;}@Override public boolean onQueryTextSubmit(String query) {// Don't care about this.return true;}@Override public void onListItemClick(ListView l, View v, int position, long id) {// Insert desired behavior here.Log.i("FragmentComplexList", "Item clicked: " + id);}// These are the Contacts rows that we will retrieve.static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {Contacts._ID,Contacts.DISPLAY_NAME,Contacts.CONTACT_STATUS,Contacts.CONTACT_PRESENCE,Contacts.PHOTO_ID,Contacts.LOOKUP_KEY,};public Loader<Cursor> onCreateLoader(int id, Bundle args) {// This is called when a new Loader needs to be created. This// sample only has one Loader, so we don't care about the ID.// First, pick the base URI to use depending on whether we are// currently filtering.Uri baseUri;if (mCurFilter != null) {baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,Uri.encode(mCurFilter));} else {baseUri = Contacts.CONTENT_URI;}// Now create and return a CursorLoader that will take care of// creating a Cursor for the data being displayed.String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("+ Contacts.HAS_PHONE_NUMBER + "=1) AND ("+ Contacts.DISPLAY_NAME + " != '' ))";return new CursorLoader(getActivity(), baseUri,CONTACTS_SUMMARY_PROJECTION, select, null,Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");}public void onLoadFinished(Loader<Cursor> loader, Cursor data) {// Swap the new cursor in. (The framework will take care of closing the// old cursor once we return.)mAdapter.swapCursor(data);}public void onLoaderReset(Loader<Cursor> loader) {// This is called when the last Cursor provided to onLoadFinished()// above is about to be closed. We need to make sure we are no// longer using it.mAdapter.swapCursor(null);} }

到此整個Loader基礎使用就介紹完了,關于Loader的高級功能,譬如自定義Loader等內容這里先不貼代碼說明,因為在這里一下子說完都會覺得蒙圈,而且接受難度也比較大,所以我們在上面這些基礎鋪墊之后乘熱先來源碼淺析,有了源碼淺析把持住全局結構后再去用Loader的高級用法就會覺得得心應手許多。

三、源碼淺析

和上面的基本使用介紹一樣,關于Loader的源碼淺析過程會涉及到Activity、Fragment、LoaderManager、Loader、AsyncLoader、CursorLoader等類。所以我們分析的過程還是和以前一樣,依據使用順序進行分析。

我們在分析之前先來看一個Loader框架概要圖,如下:

通過上面圖和前面的基礎實例你會發現Loader的框架和各個類的職責都很明確。Activity和Fragment管理LoaderManager,LoaderManager管理Loader,Loader得到數據后觸發在LoaderManager中實現的Loader的callback接口,LoaderManager在接收到Loader的callback回傳調運時觸發我們Activity或Fragment中實現的LoaderManager回調callback接口,就這樣就實現了Loader的所有功能,而我們平時寫代碼一般只用關心LoaderManager的callback實現即可;對于自定義Loader可能還需要關心AsyncTaskLoader子類的實現。

Activity及Fragment中LoadManager的管理淺析

首先我們都知道,在使用Loader的第一步就是在Activity或者Fragment中獲取LoaderManager實例,所以我們先來看下Activity和Fragment是如何管理這些LoaderManager的。

先來看看Fragment中的LoaderManager,如下:

final class FragmentState implements Parcelable {......LoaderManagerImpl mLoaderManager;boolean mLoadersStarted;boolean mCheckedForLoaderManager;......//fragment中獲取LoaderManager辦法public LoaderManager getLoaderManager() {//可以看見,一個Fragment只有一個LoaderManagerif (mLoaderManager != null) {return mLoaderManager;}if (mActivity == null) {throw new IllegalStateException("Fragment " + this + " not attached to Activity");}mCheckedForLoaderManager = true;//從Activity中獲取LoaderManager,傳入的mWho為當前Fragment的識別key,然后create傳入true表示創建!!!!!!mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, true);return mLoaderManager;}public void onStart() {mCalled = true;if (!mLoadersStarted) {mLoadersStarted = true;if (!mCheckedForLoaderManager) {mCheckedForLoaderManager = true;//如果還沒調運過getLoaderManager,那就嘗試獲取LoaderManager,傳入的create為false!!!!!mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);}//生命周期依附上LoaderManagerif (mLoaderManager != null) {mLoaderManager.doStart();}}}public void onDestroy() {mCalled = true;if (!mCheckedForLoaderManager) {mCheckedForLoaderManager = true;//如果還沒調運過getLoaderManager,那就嘗試獲取LoaderManager,傳入的create為false!!!!!mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);}//生命周期依附上LoaderManagerif (mLoaderManager != null) {mLoaderManager.doDestroy();}}void performStart() {......mCalled = false;onStart();......//生命周期依附上LoaderManagerif (mLoaderManager != null) {mLoaderManager.doReportStart();}}void performStop() {......mCalled = false;onStop();......if (mLoadersStarted) {mLoadersStarted = false;if (!mCheckedForLoaderManager) {mCheckedForLoaderManager = true;//如果還沒調運過getLoaderManager,那就嘗試獲取LoaderManager,傳入的create為false!!!!!mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);}if (mLoaderManager != null) {//生命周期依附上LoaderManagerif (mActivity == null || !mActivity.mChangingConfigurations) {mLoaderManager.doStop();} else {mLoaderManager.doRetain();}}}}void performDestroyView() {......mCalled = false;onDestroyView();......//生命周期依附上LoaderManagerif (mLoaderManager != null) {mLoaderManager.doReportNextStart();}} }

從上面可以看出,Fragment在其生命周期內會控制LoaderManager(LoaderManager其實控制了Loader)的doStart、doDestroy等方法,也就是說我們在Fragment中只管通過getLoaderManager方法來獲取LoaderManager實例,然后使用就行,別的Fragment都會幫我們處理OK的。

接下來看看Activity中的LoaderManager,如下:

public class Activity extends ContextThemeWrapperimplements ... {//mAllLoaderManagers保存了Activity與Fragment的所有LoaderManagerArrayMap<String, LoaderManagerImpl> mAllLoaderManagers;LoaderManagerImpl mLoaderManager;......//Activity中獲取LoaderManager實例的方法public LoaderManager getLoaderManager() {//可以看見,一個Activity只有一個LoaderManagerif (mLoaderManager != null) {return mLoaderManager;}mCheckedForLoaderManager = true;//咦?這不就是上面Fragment的getLoaderManager中調運的那個activity中的getLoaderManager嗎,只是和這里的參數不一樣而已mLoaderManager = getLoaderManager("(root)", mLoadersStarted, true);return mLoaderManager;}//Activity與Fragment獲取LoaderManager實例的真正方法!!LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) {//可見一個Activity維護一個mAllLoaderManagers的MAPif (mAllLoaderManagers == null) {mAllLoaderManagers = new ArrayMap<String, LoaderManagerImpl>();}//嘗試從緩存mAllLoaderManagers的MAP中獲取已經實例化的LoaderManager實例LoaderManagerImpl lm = mAllLoaderManagers.get(who);if (lm == null) {if (create) {//如果沒有找到并且需要實例化create(切記這個create參數是很重要的),就調運LoaderManagerImpl構造方法實例化一個LoaderManager對象,然后存入緩存mAllLoaderManagers的MAP中lm = new LoaderManagerImpl(who, this, started);mAllLoaderManagers.put(who, lm);}} else {lm.updateActivity(this);}return lm;}void invalidateFragment(String who) {if (mAllLoaderManagers != null) {LoaderManagerImpl lm = mAllLoaderManagers.get(who);if (lm != null && !lm.mRetaining) {//生命周期依附上LoaderManagerlm.doDestroy();mAllLoaderManagers.remove(who);}}}final void performStop() {if (mLoadersStarted) {mLoadersStarted = false;//生命周期依附上LoaderManagerif (mLoaderManager != null) {//mChangingConfigurations表示如果當前發生了配置變化則為true,否則為false!!!!!!!重點,Loader特性之一if (!mChangingConfigurations) {//當前Activity的stop不是由配置變化引起則直接調用LoaderManager的doStop()方法!!!!!!mLoaderManager.doStop();} else {//當前Activity配置變化,所以需要保存當前的loaderManager,在Activity恢復時恢復這個LoaderManager!!!!!!mLoaderManager.doRetain();}}}......}final void performDestroy() {......onDestroy();//生命周期依附上LoaderManagerif (mLoaderManager != null) {mLoaderManager.doDestroy();}......}protected void onCreate(@Nullable Bundle savedInstanceState) {if (mLastNonConfigurationInstances != null) {//從mLastNonConfigurationInstances中恢復mAllLoaderManagers(mLastNonConfigurationInstances是從onAttach中恢復的),Activity配置變化時會走這里!!!!mAllLoaderManagers = mLastNonConfigurationInstances.loaders;}......mCalled = true;}final void performStart() {......if (mAllLoaderManagers != null) {final int N = mAllLoaderManagers.size();LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];for (int i=N-1; i>=0; i--) {loaders[i] = mAllLoaderManagers.valueAt(i);}//生命周期依附上LoaderManagerfor (int i=0; i<N; i++) {LoaderManagerImpl lm = loaders[i];//調用LoaderManager.finishRetain()以及doReportStart()方法來恢復LoaderManager的狀態!!!!!lm.finishRetain();lm.doReportStart();}}mActivityTransitionState.enterReady(this);}//該方法會被ActivityThread類調用,且調運時機早于performDestroy()方法!!!!!!NonConfigurationInstances retainNonConfigurationInstances() {......NonConfigurationInstances nci = new NonConfigurationInstances();......//配置變化時保存mAllLoaderManagers!!!!!!nci.loaders = mAllLoaderManagers;return nci;} }

通過上面的分析可以發現,Activity其實真正的管理了Activity及Fragment的LoaderManager(Fragment也會管理一部分自己LoaderManager的周期),而LoaderManager又管理了Loader,可以發現他們各自的管理范圍都是十分的清晰明了的。

LoadManager及其實現類LoadManagerImpl的淺析

上面分析Activity及Fragment中獲取LoaderManager實例時已經知道,我們獲取的LoaderManager實例其實就是LoaderManagerImpl對象,而LoaderManagerImpl又是LoaderManager類的子類,所以接下來我們來分析這兩個父子類。

先看下抽象父類LoaderManager,如下

public abstract class LoaderManager {//LoaderManager的回調接口定義public interface LoaderCallbacks<D> {public Loader<D> onCreateLoader(int id, Bundle args);public void onLoadFinished(Loader<D> loader, D data);public void onLoaderReset(Loader<D> loader);}//下面這些方法沒必要再細說了,上面介紹過的public abstract <D> Loader<D> initLoader(int id, Bundle args,LoaderManager.LoaderCallbacks<D> callback);public abstract <D> Loader<D> restartLoader(int id, Bundle args,LoaderManager.LoaderCallbacks<D> callback);//會觸發回調的onLoaderReset方法public abstract void destroyLoader(int id);public abstract <D> Loader<D> getLoader(int id);public abstract void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args);public static void enableDebugLogging(boolean enabled) {LoaderManagerImpl.DEBUG = enabled;} }

可以看見LoaderManager抽象類只是定義了一些規范接口而已,那么接著我們看下抽象類LoaderManager的實現類LoaderManagerImpl,如下:

class LoaderManagerImpl extends LoaderManager {static final String TAG = "LoaderManager";static boolean DEBUG = false;//保存當前存活的Loaderfinal SparseArray<LoaderInfo> mLoaders = new SparseArray<LoaderInfo>(0);//保存已經運行完的Loaderfinal SparseArray<LoaderInfo> mInactiveLoaders = new SparseArray<LoaderInfo>(0);final String mWho;Activity mActivity;boolean mStarted;boolean mRetaining;boolean mRetainingStarted;//是否正在創建Loader,多線程中同時調運創建會導致異常boolean mCreatingLoader;//Loader的封裝類final class LoaderInfo implements Loader.OnLoadCompleteListener<Object>,Loader.OnLoadCanceledListener<Object> {final int mId;final Bundle mArgs;LoaderManager.LoaderCallbacks<Object> mCallbacks;Loader<Object> mLoader;boolean mHaveData;boolean mDeliveredData;Object mData;boolean mStarted;//mRetaining標記Activity配置變化時保持當前Loader,不用銷毀;和上面分析Activity的LoaderManager的retainNonConfigurationInstances方法關聯!!!!!!boolean mRetaining;boolean mRetainingStarted;boolean mReportNextStart;boolean mDestroyed;boolean mListenerRegistered;LoaderInfo mPendingLoader;//LoaderInfo構造方法public LoaderInfo(int id, Bundle args, LoaderManager.LoaderCallbacks<Object> callbacks) {mId = id;mArgs = args;mCallbacks = callbacks;}//啟動一個Loadervoid start() {//配置改變恢復則不用啟動,用原來的if (mRetaining && mRetainingStarted) {mStarted = true;return;}//如果已經啟動,則不用再restart了if (mStarted) {return;}mStarted = true;//如果當前封裝中mLoader為空并且通過構造方法的mCallbacks不為空則回調onCreateLoader方法創建Loaderif (mLoader == null && mCallbacks != null) {mLoader = mCallbacks.onCreateLoader(mId, mArgs);}if (mLoader != null) {if (mLoader.getClass().isMemberClass()&& !Modifier.isStatic(mLoader.getClass().getModifiers())) {//如果當前創建的Loader對象是一個非靜態內部類則拋異常!!!!!!throw new IllegalArgumentException("Object returned from onCreateLoader must not be a non-static inner member class: "+ mLoader);}if (!mListenerRegistered) {//注冊Loader的監聽方法mLoader.registerListener(mId, this);mLoader.registerOnLoadCanceledListener(this);mListenerRegistered = true;}//調運Loader的startLoading方法mLoader.startLoading();}}//Activity的配置改變時進行標志位的設置,以便可以保存,配合上面Activity的分析!!!!!!void retain() {mRetaining = true;......}//Activity配置變化后重啟后如果有數據則通知回調方法,配合上面Activity的分析!!!!!!void finishRetain() {......if (mStarted && mHaveData && !mReportNextStart) {callOnLoadFinished(mLoader, mData);}}//配合上面Activity的分析!!!!!!void reportStart() {......}//停止Loadervoid stop() {mStarted = false;if (!mRetaining) {//如果不是Activity配置變化,即不用保存則注銷掉這些回調if (mLoader != null && mListenerRegistered) {......}}}//取消掉Loadervoid cancel() {......}//銷毀掉Loadervoid destroy() {......if (mCallbacks != null && mLoader != null && mHaveData && needReset) {......try {//在destroy時如果有數據存在則調用callback的onLoaderReset方法!!!!!!mCallbacks.onLoaderReset(mLoader);} finally {......}}......if (mLoader != null) {//注銷監聽方法if (mListenerRegistered) {......}//close Cursor等重置操作mLoader.reset();}if (mPendingLoader != null) {mPendingLoader.destroy();}}//Loader被取消時回調該方法@Overridepublic void onLoadCanceled(Loader<Object> loader) {......LoaderInfo pending = mPendingLoader;//執行最新的Loaderif (pending != null) {mPendingLoader = null;mLoaders.put(mId, null);destroy();installLoader(pending);}}//加載完成時回調@Overridepublic void onLoadComplete(Loader<Object> loader, Object data) {......//執行最新的Loaderif (pending != null) {mPendingLoader = null;mLoaders.put(mId, null);destroy();installLoader(pending);return;}if (mData != data || !mHaveData) {mData = data;mHaveData = true;if (mStarted) {callOnLoadFinished(loader, data);}}......}//調用onLoadFinishedvoid callOnLoadFinished(Loader<Object> loader, Object data) {if (mCallbacks != null) {......try {//回調onLoadFinished方法mCallbacks.onLoadFinished(loader, data);} finally {......}mDeliveredData = true;}}}//!!!!!!真正LoaderManagerImpl的構造方法LoaderManagerImpl(String who, Activity activity, boolean started) {mWho = who;mActivity = activity;mStarted = started;}//更新當前Activity引用void updateActivity(Activity activity) {mActivity = activity;}//私有的創建Loader方法private LoaderInfo createLoader(int id, Bundle args,LoaderManager.LoaderCallbacks<Object> callback) {LoaderInfo info = new LoaderInfo(id, args, (LoaderManager.LoaderCallbacks<Object>)callback);//回調callback的onCreateLoader方法得到Loader對象Loader<Object> loader = callback.onCreateLoader(id, args);//把得到的Loader對象包裝成LoaderInfo對象info.mLoader = (Loader<Object>)loader;return info;}//包裝了創建Loader與install方法,并將mCreatingLoader標記置位private LoaderInfo createAndInstallLoader(int id, Bundle args,LoaderManager.LoaderCallbacks<Object> callback) {try {mCreatingLoader = true;//調運上面的私有創建方法創建LoaderInfo對象LoaderInfo info = createLoader(id, args, callback);//把創建的LoaderInfo對象傳入installLoader方法installLoader(info);return info;} finally {mCreatingLoader = false;}}void installLoader(LoaderInfo info) {//將創建的LoaderInfo對象存入mLoaders的Map中mLoaders.put(info.mId, info);if (mStarted) {//如果Activity已經started,則啟動LoaderInfo的start方法info.start();}}//public的方法,創建一個Loader,前面介紹過的@SuppressWarnings("unchecked")public <D> Loader<D> initLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {//如果多線程中正在有創建的則拋出異常(寫代碼要注意這種情況,尤其是跑Monkey容易拋出,解決辦法就是保證都在統一線程中執行!!!!!!)if (mCreatingLoader) {throw new IllegalStateException("Called while creating a loader");}//從現有的Map中嘗試獲取指定ID的LoaderInfo對象LoaderInfo info = mLoaders.get(id);if (info == null) {//發現不存在就調運上面的createAndInstallLoader創建一個info = createAndInstallLoader(id, args, (LoaderManager.LoaderCallbacks<Object>)callback);} else {//否則還用當前的Loader,只是重新賦值了callBack而已info.mCallbacks = (LoaderManager.LoaderCallbacks<Object>)callback;}if (info.mHaveData && mStarted) {//已經有數據,直接調運LoaderInfo的callOnLoadFinishedinfo.callOnLoadFinished(info.mLoader, info.mData);}//返回Loader對象return (Loader<D>)info.mLoader;}//重新創造Loader,前面介紹過的@SuppressWarnings("unchecked")public <D> Loader<D> restartLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {if (mCreatingLoader) {//如果多線程中正在有創建的則拋出異常(寫代碼要注意這種情況,尤其是跑Monkey容易拋出,解決辦法就是保證都在統一線程中執行!!!!!!)throw new IllegalStateException("Called while creating a loader");}LoaderInfo info = mLoaders.get(id);if (info != null) {LoaderInfo inactive = mInactiveLoaders.get(id);if (inactive != null) {if (info.mHaveData) {//發現是已經運行完的Loader且已經存在的Loader有數據則destroy掉運行完的Loaderinactive.mDeliveredData = false;inactive.destroy();info.mLoader.abandon();mInactiveLoaders.put(id, info);} else {if (!info.mStarted) {//有相同id的Loader還沒start則destory掉mLoaders.put(id, null);info.destroy();} else {//有一個相同id的Loader正在加載數據,但是還沒加載完,調用它的cancel()方法通知取消加載info.cancel();if (info.mPendingLoader != null) {info.mPendingLoader.destroy();info.mPendingLoader = null;}//創建一個指定id的Loader同時賦給mPendingLoader,因為這個時候已經有一個Loader正在加載數據,而且我們已經調用了其cancel()方法來通知取消加載info.mPendingLoader = createLoader(id, args, (LoaderManager.LoaderCallbacks<Object>)callback);//返回創建的Loaderreturn (Loader<D>)info.mPendingLoader.mLoader;}}} else {//終止已存在的Loaderinfo.mLoader.abandon();mInactiveLoaders.put(id, info);}}//重新創建Loader返回info = createAndInstallLoader(id, args, (LoaderManager.LoaderCallbacks<Object>)callback);return (Loader<D>)info.mLoader;}//銷毀指定id的Loaderpublic void destroyLoader(int id) {if (mCreatingLoader) {throw new IllegalStateException("Called while creating a loader");}//不解釋,單純的destoryint idx = mLoaders.indexOfKey(id);if (idx >= 0) {LoaderInfo info = mLoaders.valueAt(idx);mLoaders.removeAt(idx);info.destroy();}idx = mInactiveLoaders.indexOfKey(id);if (idx >= 0) {LoaderInfo info = mInactiveLoaders.valueAt(idx);mInactiveLoaders.removeAt(idx);info.destroy();}......}//獲取指定id的Loader對象@SuppressWarnings("unchecked")public <D> Loader<D> getLoader(int id) {if (mCreatingLoader) {throw new IllegalStateException("Called while creating a loader");}//優先獲取LoaderInfo中的mPendingLoaderLoaderInfo loaderInfo = mLoaders.get(id);if (loaderInfo != null) {if (loaderInfo.mPendingLoader != null) {return (Loader<D>)loaderInfo.mPendingLoader.mLoader;}return (Loader<D>)loaderInfo.mLoader;}return null;}...... }

我勒個去!好長,好累!通過上面粗略的分析你會發現和我們上面基礎實例介紹LoaderManager的方法時描述的一樣,每個方法都有自己的特點,發揮著各自的作用,LoaderManager的實質是將Loader對象轉換為LoaderInfo來進行管理,也就是管理了所有的Loader對象。

Loader及其實現類的淺析

上面分析了Activity及Fragment管理了LoaderManager的相關方法,LoaderManager管理了Loader的相關方法,那么接下來我們就來看看這個被管理的終極目標Loader是咋回事,還有他的子類咋回事。

先來看看我畫的一張關系圖,如下:

我去,這圖現在看可能有些嚇人,我們還是先來慢慢分析一下再說吧。

Loader基類源碼淺析

我們先來看看這個Loader基類吧,該類核心方法及內部類結構圖如下:

代碼分析如下:

public class Loader<D> {int mId;OnLoadCompleteListener<D> mListener;OnLoadCanceledListener<D> mOnLoadCanceledListener;Context mContext;boolean mStarted = false;boolean mAbandoned = false;boolean mReset = true;boolean mContentChanged = false;boolean mProcessingChange = false;//數據源變化監聽器(觀察者模式),實現了ContentObserver類public final class ForceLoadContentObserver extends ContentObserver {public ForceLoadContentObserver() {super(new Handler());}@Overridepublic boolean deliverSelfNotifications() {return true;}@Overridepublic void onChange(boolean selfChange) {//實質是調運Loader的forceLoad方法onContentChanged();}}//Loader加載完成接口,當加載完成時Loader通知loaderManager,loaderManager再回調我們initLoader方法的callbackpublic interface OnLoadCompleteListener<D> {public void onLoadComplete(Loader<D> loader, D data);}//LoaderManager中監聽cancel,同上類似public interface OnLoadCanceledListener<D> {public void onLoadCanceled(Loader<D> loader);}//構造方法public Loader(Context context) {//mContext持有Application的Context,防止泄露內存等mContext = context.getApplicationContext();}//加載完成時回調傳遞加載數據結果,實質是對OnLoadCompleteListener接口方法的封裝public void deliverResult(D data) {if (mListener != null) {mListener.onLoadComplete(this, data);}}//類似同上,對OnLoadCanceledListener的方法的封裝public void deliverCancellation() {if (mOnLoadCanceledListener != null) {mOnLoadCanceledListener.onLoadCanceled(this);}}public Context getContext() {return mContext;}public int getId() {return mId;}public void registerListener(int id, OnLoadCompleteListener<D> listener) {mListener = listener;mId = id;}public void unregisterListener(OnLoadCompleteListener<D> listener) {mListener = null;}public void registerOnLoadCanceledListener(OnLoadCanceledListener<D> listener) {mOnLoadCanceledListener = listener;}public void unregisterOnLoadCanceledListener(OnLoadCanceledListener<D> listener) {mOnLoadCanceledListener = null;}public boolean isStarted() {return mStarted;}public boolean isAbandoned() {return mAbandoned;}public boolean isReset() {return mReset;}//開始加載數據時LoaderManager會調用該方法public final void startLoading() {//設置標記mStarted = true;mReset = false;mAbandoned = false;onStartLoading();}//真正開始加載數據的地方******空方法,子類實現!!!!!!protected void onStartLoading() {}//取消Loader的方法public boolean cancelLoad() {return onCancelLoad();}//真正取消的地方******,子類實現!!!!!!return false表示取消失敗(因為已完成或未開始)protected boolean onCancelLoad() {return false;}//強制重新Loader,放棄舊數據public void forceLoad() {onForceLoad();}//真正重新Loader的地方******空方法,子類實現!!!!!!protected void onForceLoad() {}//同上public void stopLoading() {mStarted = false;onStopLoading();}protected void onStopLoading() {}//同上public void abandon() {mAbandoned = true;onAbandon();}protected void onAbandon() {}//同上public void reset() {onReset();mReset = true;mStarted = false;mAbandoned = false;mContentChanged = false;mProcessingChange = false;}protected void onReset() {}//Loader數據變化的一些標記處理public boolean takeContentChanged() {boolean res = mContentChanged;mContentChanged = false;mProcessingChange |= res;return res;}public void commitContentChanged() {mProcessingChange = false;}public void rollbackContentChanged() {if (mProcessingChange) {mContentChanged = true;}}//上面ForceLoadContentObserver內部類的onChange方法調運public void onContentChanged() {if (mStarted) {forceLoad();} else {mContentChanged = true;}}//一些方便調試的方法public String dataToString(D data)public String toString()public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) }

通過上面粗略的分析可以發現,Loader基類無非也就是一個方法接口的定義類,組織預留了一些方法供LoaderManager去調運處理,同時需要子類實現其提供的一些onXXX方法,以便LoaderManager調運Loader的方法時可以觸發Loader子類的實現邏輯。

AsyncTaskLoader抽象子類源碼淺析

上面既然說了Loader類的作用主要是規定接口,同時供LoaderManager管理,那LoaderManager管理的Loader自然需要做一些事情,也就是說我們需要繼承Loader實現一些邏輯操作。然而好在系統API已經幫我們實現了一些簡單的封裝實現,我們這里就先來看下Loader的直接子類AsyncTaskLoader吧,先來看下該抽象子類的方法及內部類粗略圖,如下:

代碼分析如下:

public abstract class AsyncTaskLoader<D> extends Loader<D> {static final String TAG = "AsyncTaskLoader";static final boolean DEBUG = false;//LoadTask內部類是對AsyncTask的封裝,實現了Runnable接口final class LoadTask extends AsyncTask<Void, Void, D> implements Runnable {......@Overrideprotected D doInBackground(Void... params) {try {//AsyncTask的子線程中執行AsyncTaskLoader的onLoadInBackground方法!!!!重點D data = AsyncTaskLoader.this.onLoadInBackground();//把執行結果數據D返回到UI線程return data;} catch (OperationCanceledException ex) {if (!isCancelled()) {throw ex;}return null;}}/* Runs on the UI thread */@Overrideprotected void onPostExecute(D data) {//AsyncTask子線程執行完畢后回調AsyncTaskLoader的dispatchOnLoadComplete方法AsyncTaskLoader.this.dispatchOnLoadComplete(this, data);}/* Runs on the UI thread */@Overrideprotected void onCancelled(D data) {//取消AsyncTask時調運AsyncTaskLoader.this.dispatchOnCancelled(this, data);}//Runnable的實現方法@Overridepublic void run() {waiting = false;AsyncTaskLoader.this.executePendingTask();}......}private final Executor mExecutor;volatile LoadTask mTask;volatile LoadTask mCancellingTask;long mUpdateThrottle;long mLastLoadCompleteTime = -10000;Handler mHandler;//public構造方法public AsyncTaskLoader(Context context) {this(context, AsyncTask.THREAD_POOL_EXECUTOR);}/** {@hide} 無法被外部調運的構造方法 */public AsyncTaskLoader(Context context, Executor executor) {super(context);mExecutor = executor;}public void setUpdateThrottle(long delayMS) {mUpdateThrottle = delayMS;if (delayMS != 0) {mHandler = new Handler();}}@Overrideprotected void onForceLoad() {super.onForceLoad();//取消當前的LoadercancelLoad();//新建task并執行mTask = new LoadTask();executePendingTask();}@Overrideprotected boolean onCancelLoad() {......}public void onCanceled(D data) {}//LoadTask的Runnable方法run中執行void executePendingTask() {if (mCancellingTask == null && mTask != null) {if (mTask.waiting) {mTask.waiting = false;mHandler.removeCallbacks(mTask);}if (mUpdateThrottle > 0) {long now = SystemClock.uptimeMillis();if (now < (mLastLoadCompleteTime+mUpdateThrottle)) {// Not yet time to do another load.mTask.waiting = true;mHandler.postAtTime(mTask, mLastLoadCompleteTime+mUpdateThrottle);return;}}//真正的觸發執行AsyncTask方法mTask.executeOnExecutor(mExecutor, (Void[]) null);}}void dispatchOnCancelled(LoadTask task, D data) {onCanceled(data);if (mCancellingTask == task) {rollbackContentChanged();mLastLoadCompleteTime = SystemClock.uptimeMillis();mCancellingTask = null;//觸發Loader的接口方法onLoadCanceled,在LoaderManager中實現deliverCancellation();executePendingTask();}}void dispatchOnLoadComplete(LoadTask task, D data) {if (mTask != task) {dispatchOnCancelled(task, data);} else {if (isAbandoned()) {// This cursor has been abandoned; just cancel the new data.onCanceled(data);} else {commitContentChanged();mLastLoadCompleteTime = SystemClock.uptimeMillis();mTask = null;//觸發Loader的接口方法onLoadComplete,在LoaderManager中實現deliverResult(data);}}}//需要子類實現!!!!!在子線程中執行public abstract D loadInBackground();//LoadTask(AsyncTask的子線程中回調)中調運protected D onLoadInBackground() {return loadInBackground();}//LoadTask(AsyncTask的onCancelLoad中回調)調運public void cancelLoadInBackground() {}public boolean isLoadInBackgroundCanceled() {return mCancellingTask != null;}//鎖標記處理public void waitForLoader() {LoadTask task = mTask;if (task != null) {task.waitForLoader();}} }

可以看見上面繼承Loader的AsyncTaskLoader其實質是提供了一個基于AsyncTask工作機制的Loader(子類LoadTask繼承AsyncTask< Void, Void, D >,并且實現了Runable接口,功能十分強大。),但是不可直接用,因為其為abstract抽象類,所以我們需要繼承實現它才可以使用,然而好在系統API已經幫我們提供了他現成的子類CursorLoader,但CursorLoader同時也限制了Loader的泛型數據為Cursor類型。當然了,我們如果想要Loader自己的類型數據那也很簡單—繼承實現AsyncTaskLoader即可,后面會給出例子的。

CursorLoader子類源碼淺析

有了上面繼承自Loader的抽象AsyncTaskLoader,接下來我們就來看看SDK為我們提供的抽象AsyncTaskLoader實現類CursorLoader,我們先來粗略看看該類的方法圖,如下:

具體代碼分析如下:

//繼承自AsyncTaskLoader,數據類型為Cursor的Loader異步加載實現類 public class CursorLoader extends AsyncTaskLoader<Cursor> {//ContentObserver的子類ForceLoadContentObserverfinal ForceLoadContentObserver mObserver;Uri mUri;String[] mProjection;String mSelection;String[] mSelectionArgs;String mSortOrder;Cursor mCursor;CancellationSignal mCancellationSignal;/* Runs on a worker thread 最核心的實現方法,在這里查詢獲取數據 */@Overridepublic Cursor loadInBackground() {synchronized (this) {if (isLoadInBackgroundCanceled()) {throw new OperationCanceledException();}mCancellationSignal = new CancellationSignal();}try {//不過多解釋,耗時的查詢操作Cursor cursor = getContext().getContentResolver().query(mUri, mProjection, mSelection,mSelectionArgs, mSortOrder, mCancellationSignal);if (cursor != null) {try {// Ensure the cursor window is filled.cursor.getCount();//給Cursor設置觀察者;ContentProvider通知Cursor的觀察者數據發生了改變,Cursor通知CursorLoader的觀察者數據發生了改變,CursorLoader通過ContentProvider重新加載新的數據cursor.registerContentObserver(mObserver);} catch (RuntimeException ex) {cursor.close();throw ex;}}return cursor;} finally {synchronized (this) {mCancellationSignal = null;}}}@Overridepublic void cancelLoadInBackground() {super.cancelLoadInBackground();synchronized (this) {if (mCancellationSignal != null) {mCancellationSignal.cancel();}}}/* Runs on the UI thread */@Overridepublic void deliverResult(Cursor cursor) {if (isReset()) {// An async query came in while the loader is stoppedif (cursor != null) {cursor.close();}return;}Cursor oldCursor = mCursor;mCursor = cursor;if (isStarted()) {super.deliverResult(cursor);}if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {oldCursor.close();}}public CursorLoader(Context context) {super(context);mObserver = new ForceLoadContentObserver();}public CursorLoader(Context context, Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {super(context);//新建一個當前類(Loader)的內部類對象,數據庫變化時調運ForceLoadContentObserver的onChange方法,onChange調運Loader的onContentChanged方法,onContentChanged調運Loader的forceLoad方法mObserver = new ForceLoadContentObserver();mUri = uri;mProjection = projection;mSelection = selection;mSelectionArgs = selectionArgs;mSortOrder = sortOrder;}@Overrideprotected void onStartLoading() {if (mCursor != null) {deliverResult(mCursor);}if (takeContentChanged() || mCursor == null) {forceLoad();}}@Overrideprotected void onStopLoading() {// Attempt to cancel the current load task if possible.cancelLoad();}@Overridepublic void onCanceled(Cursor cursor) {if (cursor != null && !cursor.isClosed()) {cursor.close();}}@Overrideprotected void onReset() {super.onReset();// Ensure the loader is stoppedonStopLoading();if (mCursor != null && !mCursor.isClosed()) {mCursor.close();}mCursor = null;}public Uri getUri() {return mUri;}public void setUri(Uri uri) {mUri = uri;}public String[] getProjection() {return mProjection;}public void setProjection(String[] projection) {mProjection = projection;}public String getSelection() {return mSelection;}public void setSelection(String selection) {mSelection = selection;}public String[] getSelectionArgs() {return mSelectionArgs;}public void setSelectionArgs(String[] selectionArgs) {mSelectionArgs = selectionArgs;}public String getSortOrder() {return mSortOrder;}public void setSortOrder(String sortOrder) {mSortOrder = sortOrder;} }

可以發現,CursorLoader的封裝大大簡化了應用開發者代碼的復雜度;它完全就是一個異步的數據庫查詢瑞士軍刀,沒有啥特別需要分析的地方,所以不再過多說明。

Loaders相關源碼淺析總結

通過上面我們的源碼分析和分析前那副圖可以總結如下結論:

一次完整的數據加載流程為Activity調用LoaderManager的doStart()方法,然后LoaderManager調用Loader的startLoading()方法,然后Loader調運AsyncTaskLoader的doingBackground()方法進行耗時數據加載,然后AsyncTaskLoader回調LoaderManager的complete數據加載完成方法,接著LoaderManager回調我們在Activity中實現的callback中的onLoadFinish()方法。

Acivity和Fragment的生命周期主動管理了LoaderManager,每個Activity用一個ArrayMap的mAllLoaderManager來保存當前Activity及其附屬Frament的唯一LoaderManager;在Activity配置發生變化時,Activity在destory前會保存mAllLoaderManager,當Activity再重新創建時,會在Activity的onAttcach()、onCreate()、performStart()方法中恢復mAllLoaderManager。

LoaderManager給Activity提供了管理自己的一些方法;同時主動管理了對應的Loader,它把每一個Loader封裝為LoadInfo對象,同時它負責主動調運管理Loader的startLoading()、stopLoading()、,forceLoad()等方法。

由于整個Activity和Fragment主動管理了Loader,所以關于Loader的釋放(譬如CursorLoader的Cursor關閉等)不需要我們人為處理,Loader框架會幫我們很好的處理的;同時特別注意,對于CursorLoader,當我們數據源發生變化時Loader框架會通過ContentObserver調用onContentChanged的forceLoad方法重新請求數據進行回調刷新。

好了,至此你會發現Loader真的很牛叉,No!應該是Google的工程師真的很牛叉,架構真的很贊,值得推薦。

四、應用層開發之Loader進階實戰

上面對于Loader的基礎使用及源碼框架都進行了簡單分析,有了上面的鋪墊我們再回過頭來看看我們開發中的一些高級技巧,通過這些高級技巧不僅是對前面源碼分析的實例驗證,也是對自己知識的積累。

ContentPorvider情況下的CurSorLoader自動刷新

在我們使用CurSorLoader時大家都會考慮一種情況的處理—–當數據庫發生變化時如何自動刷新當前UI。呵呵,我們先來說說這個原理,數據庫在數據改變時通過ContentPorvider和ContentResolver發出通知,接著ContentProvider通知Cursor的觀察者數據發生了變化,然后Cursor通知CursorLoader的觀察者數據發生了變化,接著CursorLoader通過ContentProvider加載新數據,完事調用CursorAdapter的changeCursor()用新數據替換舊數據顯示。

這個過程具體的實現步驟如下:

  • 對獲取的Cursor數據設置需要監聽的URI(即,在ContentProvider的query()方法或者Loader的loadingBackground()方法中調用Cursor的setNotificationUri()方法);

  • 在ContentProvider的insert()、update()、delete()等方法中調用ContentResolver的notifyChange()方法;

通過上面兩步我們就能享受CurSorLoader的自動數據刷新功能了;可以發現,所謂的CurSorLoader自動刷新無非就是觀察者模式的框架而已,所以不再過多說明。

特別注意:

有些人覺得為了方便可能會將上面第一步對于Cursor設置監聽直接寫在了ContentProvider的query()方法中,如下:

@Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,String sortOrder) {SQLiteDatabase database = sqLiteOpenHelper.getReadableDatabase();Cursor cursor = database.query(EmailContent.CONTACT_TABLE, projection,selection,selectionArgs, null, null, sortOrder);//設置NotificationUri監聽cursor.setNotificationUri(contentResolver, EmailContent.MESSAGE);return cursor; }

這里要提醒的是,這種寫法在某些場合下是不值得推薦的(譬如大規模上千次并發平凡的調運query操作場合),因為效率極低,他會頻繁的通過Binder進行通信,導致system_server不停的調運GC操作,以至于會使系統卡頓。

PS:因為我以前跳過一次這個坑,平時使用應用沒啥問題,但是當進行壓力測試時卻發現LogCat一直在不停的打印GC,同時導致當前系統卡頓,殺掉應用后系統就不卡了,所以基本懷疑問題就出在了應用中,于是通過很多辦法去查找(譬如dempsys content去查看個數),最終發現罪魁禍首是這個監聽頻繁調運導致的,隨將其挪到loadingBackground中不再卡頓。

不使用ContentPorvider且自定義Loader的情況下自動刷新

我們目前的項目其實都使用了ContentPorvider實現,所以就是上面講的那些情況。但是你一定會問,如果我們應用的數據不用于應用間共享,使用ContentProvider那得多麻煩啊?我先告訴你,是很麻煩,但是Android提供的CursorLoader的API必須使用ContentProvider才能實現數據加載和自動刷新。

這時候你指定會說,那還說個屁!哎,別急,你看看下面這段代碼是否會有所感觸呢,如下:

public NoProviderLoader extends AsyncTaskLoader {......ForceLoadContentObserver mObserver = new ForceLoadContentObserver();......@Overridepublic Cursor loadInBackground() {SQLiteDatabase database = sqLiteOpenHelper.getReadableDatabase();Cursor cursor = database.query(table, columns, selection, selectionArgs, groupBy, having, orderBy);if (cursor != null) {//最重要的兩行代碼!!!!!!cursor.registerContentObserver(mObserver);//給Cursor設置觀察者cursor.setNotificationUri(getContext().getContentResolver(), otificationUri);//給Cursor設置要觀察的URI}return cursor;}...... }

咦?是不是上面代碼很奇怪,異步操作的方法中沒有使用ContentProvider,而是直接讀取了數據庫。握草!這不就是我們剛剛想要的需求么,它沒有使用ContentProvider提供Cursor數據,同時實現了數據變化自動更新功能。

簡單解釋下上面代碼的原理吧,我們自定義的NoProviderLoader中定義的ForceLoadContentObserver是Loader的一個內部類,上面源碼分析已經解釋過了,當數據變化時會調運該類的onChange()方法,實質是調運了Loader的forceLoad()方法,所以能夠自動刷新,不多解釋了。

Loader自定義之AsyncTaskLoader衍生

可能看到這里你更加會舉一反三的反駁一句了,上面搞了半天都是和數據庫Cursor相關的東東,難道Loader就不能異步處理別的數據結構么?答案是能,因為你可能已經注意到了Loader和AsyncTaskLoader都是泛型類;既然這樣,那我們找貓畫虎一把唄,仿照CursorLoader自定義一個自己的異步加載試試,具體實現如下(哈哈,想了又想,這里還是直接給出官方的自定義AsyncTaskLoader好點,畢竟權威些,詳細點我查看官方自定義實現Demo):

官方對于查詢已安裝App列表的Loader實現,支持新App安裝后自動刷新的功能,實現如下:

/*** This class holds the per-item data in our Loader.*/ public static class AppEntry {public AppEntry(AppListLoader loader, ApplicationInfo info) {mLoader = loader;mInfo = info;mApkFile = new File(info.sourceDir);}public ApplicationInfo getApplicationInfo() {return mInfo;}public String getLabel() {return mLabel;}public Drawable getIcon() {if (mIcon == null) {if (mApkFile.exists()) {mIcon = mInfo.loadIcon(mLoader.mPm);return mIcon;} else {mMounted = false;}} else if (!mMounted) {// If the app wasn't mounted but is now mounted, reload// its icon.if (mApkFile.exists()) {mMounted = true;mIcon = mInfo.loadIcon(mLoader.mPm);return mIcon;}} else {return mIcon;}return mLoader.getContext().getResources().getDrawable(android.R.drawable.sym_def_app_icon);}@Override public String toString() {return mLabel;}void loadLabel(Context context) {if (mLabel == null || !mMounted) {if (!mApkFile.exists()) {mMounted = false;mLabel = mInfo.packageName;} else {mMounted = true;CharSequence label = mInfo.loadLabel(context.getPackageManager());mLabel = label != null ? label.toString() : mInfo.packageName;}}}private final AppListLoader mLoader;private final ApplicationInfo mInfo;private final File mApkFile;private String mLabel;private Drawable mIcon;private boolean mMounted; }/*** Perform alphabetical comparison of application entry objects.*/ public static final Comparator<AppEntry> ALPHA_COMPARATOR = new Comparator<AppEntry>() {private final Collator sCollator = Collator.getInstance();@Overridepublic int compare(AppEntry object1, AppEntry object2) {return sCollator.compare(object1.getLabel(), object2.getLabel());} };/*** Helper for determining if the configuration has changed in an interesting* way so we need to rebuild the app list.*/ public static class InterestingConfigChanges {final Configuration mLastConfiguration = new Configuration();int mLastDensity;boolean applyNewConfig(Resources res) {int configChanges = mLastConfiguration.updateFrom(res.getConfiguration());boolean densityChanged = mLastDensity != res.getDisplayMetrics().densityDpi;if (densityChanged || (configChanges&(ActivityInfo.CONFIG_LOCALE|ActivityInfo.CONFIG_UI_MODE|ActivityInfo.CONFIG_SCREEN_LAYOUT)) != 0) {mLastDensity = res.getDisplayMetrics().densityDpi;return true;}return false;} }/*** Helper class to look for interesting changes to the installed apps* so that the loader can be updated.*/ public static class PackageIntentReceiver extends BroadcastReceiver {final AppListLoader mLoader;public PackageIntentReceiver(AppListLoader loader) {mLoader = loader;IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);filter.addAction(Intent.ACTION_PACKAGE_REMOVED);filter.addAction(Intent.ACTION_PACKAGE_CHANGED);filter.addDataScheme("package");mLoader.getContext().registerReceiver(this, filter);// Register for events related to sdcard installation.IntentFilter sdFilter = new IntentFilter();sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);mLoader.getContext().registerReceiver(this, sdFilter);}@Override public void onReceive(Context context, Intent intent) {// Tell the loader about the change.mLoader.onContentChanged();} }/*** A custom Loader that loads all of the installed applications.*/ public static class AppListLoader extends AsyncTaskLoader<List<AppEntry>> {final InterestingConfigChanges mLastConfig = new InterestingConfigChanges();final PackageManager mPm;List<AppEntry> mApps;PackageIntentReceiver mPackageObserver;public AppListLoader(Context context) {super(context);// Retrieve the package manager for later use; note we don't// use 'context' directly but instead the save global application// context returned by getContext().mPm = getContext().getPackageManager();}/*** This is where the bulk of our work is done. This function is* called in a background thread and should generate a new set of* data to be published by the loader.*/@Override public List<AppEntry> loadInBackground() {// Retrieve all known applications.List<ApplicationInfo> apps = mPm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES |PackageManager.GET_DISABLED_COMPONENTS);if (apps == null) {apps = new ArrayList<ApplicationInfo>();}final Context context = getContext();// Create corresponding array of entries and load their labels.List<AppEntry> entries = new ArrayList<AppEntry>(apps.size());for (int i=0; i<apps.size(); i++) {AppEntry entry = new AppEntry(this, apps.get(i));entry.loadLabel(context);entries.add(entry);}// Sort the list.Collections.sort(entries, ALPHA_COMPARATOR);// Done!return entries;}/*** Called when there is new data to deliver to the client. The* super class will take care of delivering it; the implementation* here just adds a little more logic.*/@Override public void deliverResult(List<AppEntry> apps) {if (isReset()) {// An async query came in while the loader is stopped. We// don't need the result.if (apps != null) {onReleaseResources(apps);}}List<AppEntry> oldApps = mApps;mApps = apps;if (isStarted()) {// If the Loader is currently started, we can immediately// deliver its results.super.deliverResult(apps);}// At this point we can release the resources associated with// 'oldApps' if needed; now that the new result is delivered we// know that it is no longer in use.if (oldApps != null) {onReleaseResources(oldApps);}}/*** Handles a request to start the Loader.*/@Override protected void onStartLoading() {if (mApps != null) {// If we currently have a result available, deliver it// immediately.deliverResult(mApps);}// Start watching for changes in the app data.if (mPackageObserver == null) {mPackageObserver = new PackageIntentReceiver(this);}// Has something interesting in the configuration changed since we// last built the app list?boolean configChange = mLastConfig.applyNewConfig(getContext().getResources());if (takeContentChanged() || mApps == null || configChange) {// If the data has changed since the last time it was loaded// or is not currently available, start a load.forceLoad();}}/*** Handles a request to stop the Loader.*/@Override protected void onStopLoading() {// Attempt to cancel the current load task if possible.cancelLoad();}/*** Handles a request to cancel a load.*/@Override public void onCanceled(List<AppEntry> apps) {super.onCanceled(apps);// At this point we can release the resources associated with 'apps'// if needed.onReleaseResources(apps);}/*** Handles a request to completely reset the Loader.*/@Override protected void onReset() {super.onReset();// Ensure the loader is stoppedonStopLoading();// At this point we can release the resources associated with 'apps'// if needed.if (mApps != null) {onReleaseResources(mApps);mApps = null;}// Stop monitoring for changes.if (mPackageObserver != null) {getContext().unregisterReceiver(mPackageObserver);mPackageObserver = null;}}/*** Helper function to take care of releasing resources associated* with an actively loaded data set.*/protected void onReleaseResources(List<AppEntry> apps) {// For a simple List<> there is nothing to do. For something// like a Cursor, we would close it here.} }

不用多說,上面Loader為Google出品,強大的不得了,我們完全可以仿寫這個例子實現自己的請求。

如下為官方對該自定義Loader調運的Demo代碼:

public static class AppListAdapter extends ArrayAdapter<AppEntry> {private final LayoutInflater mInflater;public AppListAdapter(Context context) {super(context, android.R.layout.simple_list_item_2);mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);}public void setData(List<AppEntry> data) {clear();if (data != null) {addAll(data);}}/*** Populate new items in the list.*/@Override public View getView(int position, View convertView, ViewGroup parent) {View view;if (convertView == null) {view = mInflater.inflate(R.layout.list_item_icon_text, parent, false);} else {view = convertView;}AppEntry item = getItem(position);((ImageView)view.findViewById(R.id.icon)).setImageDrawable(item.getIcon());((TextView)view.findViewById(R.id.text)).setText(item.getLabel());return view;} }public static class AppListFragment extends ListFragmentimplements OnQueryTextListener, OnCloseListener,LoaderManager.LoaderCallbacks<List<AppEntry>> {// This is the Adapter being used to display the list's data.AppListAdapter mAdapter;// The SearchView for doing filtering.SearchView mSearchView;// If non-null, this is the current filter the user has provided.String mCurFilter;@Override public void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);// Give some text to display if there is no data. In a real// application this would come from a resource.setEmptyText("No applications");// We have a menu item to show in action bar.setHasOptionsMenu(true);// Create an empty adapter we will use to display the loaded data.mAdapter = new AppListAdapter(getActivity());setListAdapter(mAdapter);// Start out with a progress indicator.setListShown(false);// Prepare the loader. Either re-connect with an existing one,// or start a new one.getLoaderManager().initLoader(0, null, this);}public static class MySearchView extends SearchView {public MySearchView(Context context) {super(context);}// The normal SearchView doesn't clear its search text when// collapsed, so we will do this for it.@Overridepublic void onActionViewCollapsed() {setQuery("", false);super.onActionViewCollapsed();}}@Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {// Place an action bar item for searching.MenuItem item = menu.add("Search");item.setIcon(android.R.drawable.ic_menu_search);item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM| MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);mSearchView = new MySearchView(getActivity());mSearchView.setOnQueryTextListener(this);mSearchView.setOnCloseListener(this);mSearchView.setIconifiedByDefault(true);item.setActionView(mSearchView);}@Override public boolean onQueryTextChange(String newText) {// Called when the action bar search text has changed. Since this// is a simple array adapter, we can just have it do the filtering.mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;mAdapter.getFilter().filter(mCurFilter);return true;}@Override public boolean onQueryTextSubmit(String query) {// Don't care about this.return true;}@Overridepublic boolean onClose() {if (!TextUtils.isEmpty(mSearchView.getQuery())) {mSearchView.setQuery(null, true);}return true;}@Override public void onListItemClick(ListView l, View v, int position, long id) {// Insert desired behavior here.Log.i("LoaderCustom", "Item clicked: " + id);}@Override public Loader<List<AppEntry>> onCreateLoader(int id, Bundle args) {// This is called when a new Loader needs to be created. This// sample only has one Loader with no arguments, so it is simple.return new AppListLoader(getActivity());}@Override public void onLoadFinished(Loader<List<AppEntry>> loader, List<AppEntry> data) {// Set the new data in the adapter.mAdapter.setData(data);// The list should now be shown.if (isResumed()) {setListShown(true);} else {setListShownNoAnimation(true);}}@Override public void onLoaderReset(Loader<List<AppEntry>> loader) {// Clear the data in the adapter.mAdapter.setData(null);} }

強大的一逼!這下滿技能,不解釋,自己看。

進階總結

通過前面基礎實例、源碼分析、進階演示你會發現Loader的真的非常好用,非常牛逼,牛逼的我不想再解釋啥了,自己體會吧。

PS:之前看見微博上有人討論AsyncTaskLoader與AsyncTask的區別,這下徹底明朗了,看完源碼我們再回過頭來總結性的說說他們二者區別,如下:

class優勢劣勢
AsyncTaskLoader會自動刷新數據變化;會自動處理Activiy配置變化造成的影響;適合處理純數據加載不能實時通知UI刷新;不能在onLoadFinished時主動切換生命周期(譬如replace Fragment)
AsyncTask可以與UI實時交互及replace操作不會自動處理Activiy配置變化造成的影響

 
好了,該撕逼的也撕了,該裝逼的也裝了,該分析的也分析了,該學習的也學到了,接下來就是看自己如何帶著Loader去叱詫風云了。

總結

以上是生活随笔為你收集整理的Android Loader机制全面详解及源码浅析的全部內容,希望文章能夠幫你解決所遇到的問題。

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

麻豆国产丝袜白领秘书在线观看 | 免费人成网站视频在线观看 | 日本又色又爽又黄的a片18禁 | 超碰97人人射妻 | 夜先锋av资源网站 | 亚洲中文字幕无码一久久区 | 久久亚洲日韩精品一区二区三区 | 清纯唯美经典一区二区 | 国产av人人夜夜澡人人爽麻豆 | 麻豆国产人妻欲求不满 | 国产人妻大战黑人第1集 | 特黄特色大片免费播放器图片 | 任你躁在线精品免费 | 丰满少妇女裸体bbw | 成熟人妻av无码专区 | 日产国产精品亚洲系列 | 国产美女精品一区二区三区 | 久久人人爽人人爽人人片av高清 | 免费视频欧美无人区码 | 亚洲啪av永久无码精品放毛片 | 强辱丰满人妻hd中文字幕 | 亚洲欧美国产精品久久 | 日本熟妇乱子伦xxxx | 成人精品视频一区二区 | 人妻插b视频一区二区三区 | 亚洲精品成人av在线 | 久久综合久久自在自线精品自 | 精品无码一区二区三区爱欲 | 1000部啪啪未满十八勿入下载 | 日韩av激情在线观看 | 中文亚洲成a人片在线观看 | 成人精品天堂一区二区三区 | 久久国产自偷自偷免费一区调 | 中文字幕人妻无码一夲道 | 永久免费观看美女裸体的网站 | 国产成人一区二区三区别 | 又大又紧又粉嫩18p少妇 | 美女扒开屁股让男人桶 | 国产成人综合美国十次 | 波多野42部无码喷潮在线 | 大色综合色综合网站 | 成人综合网亚洲伊人 | 蜜桃视频韩日免费播放 | 美女黄网站人色视频免费国产 | 国模大胆一区二区三区 | 少妇性俱乐部纵欲狂欢电影 | 欧洲vodafone精品性 | 亚洲中文字幕av在天堂 | 日韩无套无码精品 | 成人动漫在线观看 | 久久久久免费看成人影片 | 久久精品人人做人人综合 | 欧美日韩久久久精品a片 | 高清无码午夜福利视频 | 国产成人久久精品流白浆 | 国产精品久久久久影院嫩草 | 久久久久人妻一区精品色欧美 | av在线亚洲欧洲日产一区二区 | 国内丰满熟女出轨videos | 在线观看免费人成视频 | 久久 国产 尿 小便 嘘嘘 | www一区二区www免费 | 四十如虎的丰满熟妇啪啪 | 色一情一乱一伦一区二区三欧美 | 国产三级久久久精品麻豆三级 | 无码免费一区二区三区 | 国产精品毛片一区二区 | 男女爱爱好爽视频免费看 | 中文字幕无线码 | 亚洲欧美日韩国产精品一区二区 | 国产av一区二区精品久久凹凸 | 久9re热视频这里只有精品 | 国产精品99爱免费视频 | 亚洲精品一区国产 | 久久久久久国产精品无码下载 | 色婷婷av一区二区三区之红樱桃 | 无人区乱码一区二区三区 | 粉嫩少妇内射浓精videos | 亚洲人交乣女bbw | 白嫩日本少妇做爰 | 久久综合久久自在自线精品自 | 97夜夜澡人人爽人人喊中国片 | 亚洲乱亚洲乱妇50p | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 日产精品高潮呻吟av久久 | 最近的中文字幕在线看视频 | 日本精品人妻无码77777 天堂一区人妻无码 | 色欲人妻aaaaaaa无码 | 欧洲美熟女乱又伦 | 一本一道久久综合久久 | 蜜臀av无码人妻精品 | 亚洲成av人片在线观看无码不卡 | 欧美黑人巨大xxxxx | 日日天干夜夜狠狠爱 | 精品国产一区二区三区四区 | 4hu四虎永久在线观看 | 国产 精品 自在自线 | 老熟女乱子伦 | 无遮挡国产高潮视频免费观看 | 色综合久久久无码中文字幕 | 国产一区二区三区四区五区加勒比 | 色欲av亚洲一区无码少妇 | 精品无码一区二区三区爱欲 | a片免费视频在线观看 | 欧美亚洲日韩国产人成在线播放 | 国产欧美精品一区二区三区 | 精品久久久无码中文字幕 | 麻豆国产97在线 | 欧洲 | 国产97人人超碰caoprom | 国产人妻精品午夜福利免费 | www国产亚洲精品久久网站 | 久久精品中文字幕一区 | 亚洲中文无码av永久不收费 | 色情久久久av熟女人妻网站 | 久久精品视频在线看15 | 精品久久久无码中文字幕 | 一本大道久久东京热无码av | 亚洲乱码国产乱码精品精 | 男女性色大片免费网站 | 国产农村乱对白刺激视频 | 97人妻精品一区二区三区 | 精品一区二区不卡无码av | 蜜桃视频插满18在线观看 | av人摸人人人澡人人超碰下载 | 中文字幕亚洲情99在线 | 青青久在线视频免费观看 | 色妞www精品免费视频 | 久久精品中文字幕大胸 | 欧美日韩亚洲国产精品 | 亚洲国产成人a精品不卡在线 | 午夜理论片yy44880影院 | 中文字幕 亚洲精品 第1页 | 成人免费视频视频在线观看 免费 | 久久久精品国产sm最大网站 | 一本色道久久综合狠狠躁 | 欧美人与禽zoz0性伦交 | 欧美日韩一区二区免费视频 | 婷婷色婷婷开心五月四房播播 | 婷婷丁香五月天综合东京热 | 天堂а√在线中文在线 | 在线观看欧美一区二区三区 | 欧洲精品码一区二区三区免费看 | 国产成人精品一区二区在线小狼 | aⅴ亚洲 日韩 色 图网站 播放 | 国产精品99久久精品爆乳 | 无码吃奶揉捏奶头高潮视频 | 中文无码精品a∨在线观看不卡 | 无码成人精品区在线观看 | 无码中文字幕色专区 | 亚洲 另类 在线 欧美 制服 | 国产高潮视频在线观看 | 九九久久精品国产免费看小说 | 欧美老妇与禽交 | 中文字幕人成乱码熟女app | 在线欧美精品一区二区三区 | 又大又硬又爽免费视频 | 九一九色国产 | 欧美成人家庭影院 | 女高中生第一次破苞av | 无码人妻出轨黑人中文字幕 | 一本加勒比波多野结衣 | 少妇被黑人到高潮喷出白浆 | 亚洲欧美日韩综合久久久 | 小泽玛莉亚一区二区视频在线 | 亚洲精品午夜国产va久久成人 | 亚洲伊人久久精品影院 | 日本精品人妻无码免费大全 | 无码av免费一区二区三区试看 | 黑人巨大精品欧美黑寡妇 | 精品国产一区二区三区四区在线看 | 日韩av激情在线观看 | 日韩精品无码一本二本三本色 | 高潮毛片无遮挡高清免费 | 亚洲精品无码人妻无码 | 亚洲中文字幕在线观看 | 夜精品a片一区二区三区无码白浆 | 成熟人妻av无码专区 | 国产精品久久久久久亚洲毛片 | 青春草在线视频免费观看 | 色五月五月丁香亚洲综合网 | 亚洲 另类 在线 欧美 制服 | 四虎永久在线精品免费网址 | 亚洲热妇无码av在线播放 | 精品人人妻人人澡人人爽人人 | 无码成人精品区在线观看 | 宝宝好涨水快流出来免费视频 | 久久综合网欧美色妞网 | 国产网红无码精品视频 | 国产亚洲人成a在线v网站 | 夫妻免费无码v看片 | 丁香啪啪综合成人亚洲 | 漂亮人妻洗澡被公强 日日躁 | 午夜福利试看120秒体验区 | 亚洲人成影院在线观看 | 免费中文字幕日韩欧美 | 婷婷丁香五月天综合东京热 | 成人性做爰aaa片免费看 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 亚洲中文字幕久久无码 | 人妻有码中文字幕在线 | 国产人妻精品一区二区三区 | 偷窥村妇洗澡毛毛多 | 成人精品天堂一区二区三区 | 两性色午夜视频免费播放 | 久久人人爽人人爽人人片av高清 | 国产成人无码av在线影院 | 久久综合久久自在自线精品自 | 久久aⅴ免费观看 | 99久久精品国产一区二区蜜芽 | 波多野结衣乳巨码无在线观看 | 网友自拍区视频精品 | 国产av一区二区三区最新精品 | 久久人人爽人人人人片 | 亚洲 a v无 码免 费 成 人 a v | 国产成人精品三级麻豆 | 成人欧美一区二区三区黑人 | 日韩人妻系列无码专区 | 1000部啪啪未满十八勿入下载 | 丝袜 中出 制服 人妻 美腿 | 曰韩少妇内射免费播放 | 久久久久久九九精品久 | 狠狠综合久久久久综合网 | 亚洲成av人在线观看网址 | 无码精品人妻一区二区三区av | 欧美一区二区三区 | 一本久道久久综合狠狠爱 | 精品无人国产偷自产在线 | 国产亲子乱弄免费视频 | 无码国内精品人妻少妇 | 丰满少妇熟乱xxxxx视频 | 亚洲区小说区激情区图片区 | 精品一区二区不卡无码av | 久久精品无码一区二区三区 | 精品偷拍一区二区三区在线看 | 亚洲国精产品一二二线 | 日本一卡二卡不卡视频查询 | 四虎影视成人永久免费观看视频 | 天干天干啦夜天干天2017 | 国产激情综合五月久久 | 日日干夜夜干 | 天下第一社区视频www日本 | 丰满岳乱妇在线观看中字无码 | 精品无码国产自产拍在线观看蜜 | 中文字幕人妻无码一夲道 | 中文字幕无码av波多野吉衣 | 一本无码人妻在中文字幕免费 | 又色又爽又黄的美女裸体网站 | 日韩精品无码一区二区中文字幕 | 久久成人a毛片免费观看网站 | 一本精品99久久精品77 | 国产在线aaa片一区二区99 | 成人欧美一区二区三区黑人免费 | 日本一区二区更新不卡 | 日产精品99久久久久久 | 日韩少妇内射免费播放 | 亚洲成av人影院在线观看 | 人人澡人人妻人人爽人人蜜桃 | 成人无码精品一区二区三区 | 亚洲精品国产a久久久久久 | 亚洲国产成人av在线观看 | 亚洲精品午夜国产va久久成人 | 精品国产一区av天美传媒 | 欧美精品一区二区精品久久 | 小鲜肉自慰网站xnxx | 一本久久伊人热热精品中文字幕 | av无码不卡在线观看免费 | 西西人体www44rt大胆高清 | 亚洲日韩中文字幕在线播放 | 性生交大片免费看l | 好男人www社区 | 内射欧美老妇wbb | 亚洲一区二区三区偷拍女厕 | 日韩无套无码精品 | 少妇被粗大的猛进出69影院 | 亚洲精品久久久久久一区二区 | 欧美成人午夜精品久久久 | 亚洲午夜福利在线观看 | 中文字幕久久久久人妻 | 无码人妻久久一区二区三区不卡 | 欧美 丝袜 自拍 制服 另类 | 久久99精品久久久久久动态图 | 色欲久久久天天天综合网精品 | 无码人中文字幕 | 乱码午夜-极国产极内射 | 永久免费观看美女裸体的网站 | 久久99精品国产麻豆蜜芽 | 99久久亚洲精品无码毛片 | 一本久道久久综合婷婷五月 | 正在播放老肥熟妇露脸 | 亚洲日韩av一区二区三区四区 | 免费无码午夜福利片69 | 日本精品少妇一区二区三区 | 色婷婷欧美在线播放内射 | 久久精品无码一区二区三区 | 久久精品女人天堂av免费观看 | 亚洲人成影院在线观看 | 国产乱码精品一品二品 | 久久无码中文字幕免费影院蜜桃 | 奇米影视7777久久精品 | 色综合天天综合狠狠爱 | 无码人妻丰满熟妇区五十路百度 | 国产精品二区一区二区aⅴ污介绍 | 国产在线一区二区三区四区五区 | 日韩av无码中文无码电影 | 亚洲欧美中文字幕5发布 | 又大又硬又爽免费视频 | 色欲av亚洲一区无码少妇 | 国产亚洲美女精品久久久2020 | 精品一区二区不卡无码av | 麻豆蜜桃av蜜臀av色欲av | 亚洲精品综合五月久久小说 | 荡女精品导航 | 特级做a爰片毛片免费69 | 色婷婷av一区二区三区之红樱桃 | 国内老熟妇对白xxxxhd | 国产高清av在线播放 | 清纯唯美经典一区二区 | 精品 日韩 国产 欧美 视频 | 天堂一区人妻无码 | 少妇被黑人到高潮喷出白浆 | 国产成人无码a区在线观看视频app | 日本精品久久久久中文字幕 | 成人试看120秒体验区 | 亚洲精品国偷拍自产在线麻豆 | 久精品国产欧美亚洲色aⅴ大片 | 国产高清不卡无码视频 | 2020久久香蕉国产线看观看 | 无码国产乱人伦偷精品视频 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 在线亚洲高清揄拍自拍一品区 | 噜噜噜亚洲色成人网站 | v一区无码内射国产 | 国产人妻人伦精品 | 少妇性荡欲午夜性开放视频剧场 | 精品一区二区三区无码免费视频 | 日韩欧美群交p片內射中文 | 草草网站影院白丝内射 | 精品无码国产一区二区三区av | 久久久久成人精品免费播放动漫 | 人人爽人人澡人人高潮 | 久久这里只有精品视频9 | 国内揄拍国内精品少妇国语 | 成人动漫在线观看 | 亚洲中文字幕在线无码一区二区 | 国产精品无码久久av | 真人与拘做受免费视频 | 性欧美疯狂xxxxbbbb | 久久久久久久女国产乱让韩 | 亚洲综合在线一区二区三区 | 久久亚洲中文字幕精品一区 | 国产人妻人伦精品1国产丝袜 | 亚洲综合无码一区二区三区 | 精品人妻人人做人人爽夜夜爽 | 久久久久久久人妻无码中文字幕爆 | 99国产欧美久久久精品 | 成人欧美一区二区三区黑人 | 97人妻精品一区二区三区 | 少妇性l交大片欧洲热妇乱xxx | 亚洲国产欧美日韩精品一区二区三区 | 丰满人妻精品国产99aⅴ | 久久人人爽人人人人片 | 亚洲欧洲日本综合aⅴ在线 | 中文字幕日产无线码一区 | 鲁大师影院在线观看 | 精品国产av色一区二区深夜久久 | 熟妇激情内射com | 沈阳熟女露脸对白视频 | 天天躁夜夜躁狠狠是什么心态 | 国内精品九九久久久精品 | 麻豆国产丝袜白领秘书在线观看 | 曰本女人与公拘交酡免费视频 | 一区二区三区乱码在线 | 欧洲 | 亚洲人成影院在线无码按摩店 | 少妇人妻偷人精品无码视频 | 蜜臀av在线观看 在线欧美精品一区二区三区 | 国产乱子伦视频在线播放 | 日韩精品成人一区二区三区 | 久久久无码中文字幕久... | 狂野欧美激情性xxxx | 色狠狠av一区二区三区 | 免费人成网站视频在线观看 | 亚洲精品国产a久久久久久 | 亚洲aⅴ无码成人网站国产app | 免费网站看v片在线18禁无码 | 伊人久久大香线蕉av一区二区 | 特级做a爰片毛片免费69 | 在线播放亚洲第一字幕 | 男人的天堂av网站 | 久久久久av无码免费网 | 亚洲成a人片在线观看无码3d | av香港经典三级级 在线 | 国内揄拍国内精品少妇国语 | 日韩精品成人一区二区三区 | 国产午夜精品一区二区三区嫩草 | 精品偷拍一区二区三区在线看 | 中文字幕无码日韩专区 | 日韩亚洲欧美精品综合 | 亚洲经典千人经典日产 | 色综合视频一区二区三区 | 天干天干啦夜天干天2017 | 狂野欧美性猛xxxx乱大交 | 亚洲国产精品无码久久久久高潮 | 1000部啪啪未满十八勿入下载 | 国产情侣作爱视频免费观看 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 好爽又高潮了毛片免费下载 | 国产精品亚洲五月天高清 | 大肉大捧一进一出好爽视频 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 激情亚洲一区国产精品 | 日本熟妇大屁股人妻 | 亚洲综合在线一区二区三区 | 久久久婷婷五月亚洲97号色 | 亚洲成av人综合在线观看 | 高清国产亚洲精品自在久久 | 一本一道久久综合久久 | 九月婷婷人人澡人人添人人爽 | 巨爆乳无码视频在线观看 | 免费人成在线观看网站 | 久久综合给久久狠狠97色 | 国产精品怡红院永久免费 | 亚洲aⅴ无码成人网站国产app | 婷婷六月久久综合丁香 | 日本大乳高潮视频在线观看 | 亚洲欧洲日本综合aⅴ在线 | 亚洲成av人片天堂网无码】 | 国产真实伦对白全集 | 又粗又大又硬毛片免费看 | 97精品人妻一区二区三区香蕉 | 蜜桃视频韩日免费播放 | 婷婷五月综合缴情在线视频 | 高清无码午夜福利视频 | 日韩成人一区二区三区在线观看 | 无码任你躁久久久久久久 | 亚洲综合无码一区二区三区 | 色综合久久88色综合天天 | 国产精品久久久久久亚洲毛片 | 国模大胆一区二区三区 | 亚洲a无码综合a国产av中文 | 成人精品视频一区二区三区尤物 | 四虎影视成人永久免费观看视频 | 蜜桃臀无码内射一区二区三区 | 黑人巨大精品欧美黑寡妇 | 无遮挡国产高潮视频免费观看 | 美女毛片一区二区三区四区 | 影音先锋中文字幕无码 | 精品厕所偷拍各类美女tp嘘嘘 | 草草网站影院白丝内射 | 欧美日韩视频无码一区二区三 | 日日躁夜夜躁狠狠躁 | 99视频精品全部免费免费观看 | 中文字幕av日韩精品一区二区 | 国产亚洲日韩欧美另类第八页 | 亚洲理论电影在线观看 | 欧洲熟妇精品视频 | 亚洲成av人片在线观看无码不卡 | 国产在线精品一区二区三区直播 | 国产欧美精品一区二区三区 | 成熟妇人a片免费看网站 | 亚洲中文字幕va福利 | 精品无人区无码乱码毛片国产 | 中文字幕乱码人妻二区三区 | 国产美女极度色诱视频www | 中文字幕乱码中文乱码51精品 | 免费国产成人高清在线观看网站 | 国产精品永久免费视频 | 欧美国产日产一区二区 | 欧美熟妇另类久久久久久不卡 | 日韩视频 中文字幕 视频一区 | 中文亚洲成a人片在线观看 | 亚洲欧洲中文日韩av乱码 | 欧美日韩一区二区三区自拍 | 亚洲毛片av日韩av无码 | 日韩精品乱码av一区二区 | 成人毛片一区二区 | 人人妻人人澡人人爽欧美一区九九 | 任你躁国产自任一区二区三区 | 国产av无码专区亚洲a∨毛片 | 丰满人妻一区二区三区免费视频 | 中国女人内谢69xxxx | 色综合久久久无码中文字幕 | 久久午夜无码鲁丝片秋霞 | 国产小呦泬泬99精品 | 四虎影视成人永久免费观看视频 | 一本久道久久综合婷婷五月 | 成在人线av无码免观看麻豆 | 无码人中文字幕 | 5858s亚洲色大成网站www | 免费乱码人妻系列无码专区 | 熟妇人妻无乱码中文字幕 | 国产农村妇女高潮大叫 | 亚洲人成影院在线无码按摩店 | 精品国产青草久久久久福利 | 老熟妇乱子伦牲交视频 | 久久无码中文字幕免费影院蜜桃 | 无码免费一区二区三区 | 老子影院午夜伦不卡 | 精品亚洲韩国一区二区三区 | 国产做国产爱免费视频 | 亚洲爆乳大丰满无码专区 | 亚洲午夜久久久影院 | 在线a亚洲视频播放在线观看 | 久久久久99精品国产片 | 日日噜噜噜噜夜夜爽亚洲精品 | 国产精品高潮呻吟av久久 | 无码av免费一区二区三区试看 | 亚洲乱码国产乱码精品精 | 丁香啪啪综合成人亚洲 | 欧美性生交xxxxx久久久 | 国产区女主播在线观看 | 久久99热只有频精品8 | 欧美日本免费一区二区三区 | 国产精品久久久午夜夜伦鲁鲁 | 中文字幕无码乱人伦 | 全球成人中文在线 | 丰满护士巨好爽好大乳 | 欧美第一黄网免费网站 | 久久精品中文闷骚内射 | 亚洲成av人综合在线观看 | 久久精品中文闷骚内射 | 特黄特色大片免费播放器图片 | 内射老妇bbwx0c0ck | 色综合天天综合狠狠爱 | 麻豆av传媒蜜桃天美传媒 | 中文字幕人妻丝袜二区 | 任你躁在线精品免费 | 撕开奶罩揉吮奶头视频 | 久久久久久久久蜜桃 | 亚洲一区二区三区播放 | 国产 浪潮av性色四虎 | 亚洲高清偷拍一区二区三区 | 欧美人妻一区二区三区 | 亚洲国产av美女网站 | 美女黄网站人色视频免费国产 | 亚洲高清偷拍一区二区三区 | 无码人妻精品一区二区三区下载 | 国产猛烈高潮尖叫视频免费 | 久久久久se色偷偷亚洲精品av | 亚洲精品午夜无码电影网 | 久久亚洲精品中文字幕无男同 | 精品国产福利一区二区 | 1000部夫妻午夜免费 | 久久久国产精品无码免费专区 | 亚洲中文无码av永久不收费 | 男女下面进入的视频免费午夜 | 精品夜夜澡人妻无码av蜜桃 | 亚洲自偷自偷在线制服 | 日韩精品乱码av一区二区 | 亚洲乱码日产精品bd | 色五月五月丁香亚洲综合网 | 2020最新国产自产精品 | 久久精品女人的天堂av | 久久人人97超碰a片精品 | 激情五月综合色婷婷一区二区 | 成人免费视频视频在线观看 免费 | 少妇无码av无码专区在线观看 | 国产97人人超碰caoprom | 天堂а√在线地址中文在线 | 午夜时刻免费入口 | 丰满少妇女裸体bbw | 51国偷自产一区二区三区 | 两性色午夜免费视频 | 一本大道久久东京热无码av | 俺去俺来也www色官网 | 亚洲 a v无 码免 费 成 人 a v | 成熟女人特级毛片www免费 | 亚洲日韩一区二区 | 久久国语露脸国产精品电影 | 久久久久久久久蜜桃 | 久久99精品久久久久久 | 精品人妻人人做人人爽夜夜爽 | 欧美日本日韩 | 黑人大群体交免费视频 | 撕开奶罩揉吮奶头视频 | 国产精品人妻一区二区三区四 | 色综合久久88色综合天天 | 成人无码视频免费播放 | 在线亚洲高清揄拍自拍一品区 | 亚洲大尺度无码无码专区 | 一区二区传媒有限公司 | 精品国产一区二区三区四区在线看 | 亚洲成a人一区二区三区 | 野外少妇愉情中文字幕 | 欧美老妇与禽交 | 国产欧美亚洲精品a | 国产情侣作爱视频免费观看 | 日本精品人妻无码免费大全 | 色爱情人网站 | 午夜性刺激在线视频免费 | 狠狠色噜噜狠狠狠7777奇米 | 国产成人无码区免费内射一片色欲 | 永久免费观看美女裸体的网站 | 无码人妻黑人中文字幕 | 国产精品办公室沙发 | 久久久久亚洲精品男人的天堂 | 国产三级精品三级男人的天堂 | 国产精品第一国产精品 | 中文精品无码中文字幕无码专区 | 国产综合在线观看 | 亚洲呦女专区 | 免费无码一区二区三区蜜桃大 | 国产suv精品一区二区五 | 国产情侣作爱视频免费观看 | 中文字幕乱码人妻无码久久 | 国产97人人超碰caoprom | 无码人妻av免费一区二区三区 | 1000部啪啪未满十八勿入下载 | 国产国语老龄妇女a片 | 国产激情精品一区二区三区 | 久久综合狠狠综合久久综合88 | 欧美性生交xxxxx久久久 | 无码人妻精品一区二区三区下载 | 99国产欧美久久久精品 | 99久久久国产精品无码免费 | 窝窝午夜理论片影院 | 国产在线aaa片一区二区99 | 自拍偷自拍亚洲精品被多人伦好爽 | 国产色在线 | 国产 | 精品日本一区二区三区在线观看 | 中文字幕 人妻熟女 | 九月婷婷人人澡人人添人人爽 | 国内精品久久毛片一区二区 | 亚洲精品综合五月久久小说 | 男女猛烈xx00免费视频试看 | 欧美激情综合亚洲一二区 | 日本欧美一区二区三区乱码 | 欧美成人家庭影院 | 无套内谢老熟女 | 大乳丰满人妻中文字幕日本 | 在线观看欧美一区二区三区 | 人人妻人人澡人人爽精品欧美 | 国产精品久久久久无码av色戒 | 99精品视频在线观看免费 | 97色伦图片97综合影院 | 亚洲熟妇色xxxxx欧美老妇 | 精品国产一区二区三区四区在线看 | 国产精品第一区揄拍无码 | 亚洲国产精品毛片av不卡在线 | 欧美喷潮久久久xxxxx | 一本久道久久综合狠狠爱 | 国产区女主播在线观看 | 樱花草在线播放免费中文 | 欧洲熟妇精品视频 | 国产在线精品一区二区高清不卡 | 久久精品国产精品国产精品污 | 国产午夜亚洲精品不卡下载 | 7777奇米四色成人眼影 | 亚洲乱码日产精品bd | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 午夜精品久久久内射近拍高清 | 波多野结衣高清一区二区三区 | 水蜜桃av无码 | 国产精品久久久午夜夜伦鲁鲁 | 成人欧美一区二区三区黑人免费 | 久久久成人毛片无码 | 中文字幕人妻无码一夲道 | 极品嫩模高潮叫床 | 亚洲s码欧洲m码国产av | 无遮挡啪啪摇乳动态图 | 在教室伦流澡到高潮hnp视频 | 久久久精品国产sm最大网站 | 丝袜 中出 制服 人妻 美腿 | 国内少妇偷人精品视频免费 | 67194成是人免费无码 | 国产av剧情md精品麻豆 | 正在播放东北夫妻内射 | 狠狠综合久久久久综合网 | 午夜精品一区二区三区在线观看 | 在线观看国产一区二区三区 | 特黄特色大片免费播放器图片 | 欧美老熟妇乱xxxxx | 黑人巨大精品欧美黑寡妇 | 亚洲人交乣女bbw | 性欧美videos高清精品 | 99久久人妻精品免费二区 | 国产精品高潮呻吟av久久 | 精品人妻人人做人人爽夜夜爽 | 久久久久成人片免费观看蜜芽 | 无套内射视频囯产 | 中文精品无码中文字幕无码专区 | 狠狠噜狠狠狠狠丁香五月 | 无码人妻丰满熟妇区毛片18 | 亚洲欧美日韩成人高清在线一区 | 中文毛片无遮挡高清免费 | 狂野欧美性猛xxxx乱大交 | 中文字幕无码免费久久99 | 台湾无码一区二区 | 亚洲熟熟妇xxxx | www国产精品内射老师 | 亚洲国产午夜精品理论片 | 亚洲乱码日产精品bd | 欧美成人免费全部网站 | 男人的天堂av网站 | 蜜桃视频韩日免费播放 | 国产成人综合美国十次 | 中文字幕无码免费久久99 | 亚洲码国产精品高潮在线 | 久久99久久99精品中文字幕 | 久久无码中文字幕免费影院蜜桃 | 亚洲日韩精品欧美一区二区 | 日本一区二区三区免费高清 | 天下第一社区视频www日本 | 99精品视频在线观看免费 | 狠狠cao日日穞夜夜穞av | 国产乱人伦偷精品视频 | 国产后入清纯学生妹 | 亚洲の无码国产の无码影院 | 日韩av无码一区二区三区 | 性欧美videos高清精品 | 成人精品一区二区三区中文字幕 | 亚洲日本在线电影 | 国产特级毛片aaaaaa高潮流水 | 无码成人精品区在线观看 | 色婷婷香蕉在线一区二区 | 人妻无码久久精品人妻 | 俺去俺来也在线www色官网 | 综合人妻久久一区二区精品 | 国产69精品久久久久app下载 | 中文字幕人妻无码一夲道 | 亚洲狠狠色丁香婷婷综合 | 精品 日韩 国产 欧美 视频 | 欧美 丝袜 自拍 制服 另类 | 久久国内精品自在自线 | 中文精品久久久久人妻不卡 | 无码帝国www无码专区色综合 | 国产日产欧产精品精品app | 自拍偷自拍亚洲精品10p | 无码中文字幕色专区 | 东北女人啪啪对白 | 日日摸夜夜摸狠狠摸婷婷 | 99久久久国产精品无码免费 | 久久久久久国产精品无码下载 | 97夜夜澡人人双人人人喊 | 一本色道久久综合狠狠躁 | 永久免费观看国产裸体美女 | 动漫av网站免费观看 | 人妻夜夜爽天天爽三区 | 国产精品久久久久9999小说 | 蜜桃臀无码内射一区二区三区 | 久久亚洲中文字幕精品一区 | 亚洲欧美国产精品专区久久 | 亚洲s码欧洲m码国产av | 久久国产劲爆∧v内射 | 久久精品女人的天堂av | 狂野欧美性猛交免费视频 | 色 综合 欧美 亚洲 国产 | 国产在热线精品视频 | 精品国精品国产自在久国产87 | 麻豆精品国产精华精华液好用吗 | 国产成人精品无码播放 | 一区二区传媒有限公司 | 久久人妻内射无码一区三区 | 天堂无码人妻精品一区二区三区 | 国产精品二区一区二区aⅴ污介绍 | 蜜桃臀无码内射一区二区三区 | 久久精品人妻少妇一区二区三区 | 亚洲 欧美 激情 小说 另类 | 久久国产自偷自偷免费一区调 | 精品国产麻豆免费人成网站 | 国产精品美女久久久久av爽李琼 | 久久亚洲日韩精品一区二区三区 | 成人aaa片一区国产精品 | 人妻体内射精一区二区三四 | 最新国产乱人伦偷精品免费网站 | 国产乱人伦偷精品视频 | 天堂亚洲2017在线观看 | 国产精品办公室沙发 | 日本一区二区三区免费高清 | 欧美性猛交内射兽交老熟妇 | 日本大香伊一区二区三区 | 国产美女极度色诱视频www | 色五月丁香五月综合五月 | 国产无遮挡又黄又爽免费视频 | 久久国产精品二国产精品 | 日本精品人妻无码免费大全 | а√资源新版在线天堂 | 四虎国产精品一区二区 | 一本久道久久综合婷婷五月 | 国产97色在线 | 免 | 狠狠躁日日躁夜夜躁2020 | 99久久精品日本一区二区免费 | 亚洲日韩精品欧美一区二区 | 少妇太爽了在线观看 | 欧美野外疯狂做受xxxx高潮 | 亚洲成a人片在线观看日本 | 欧美高清在线精品一区 | 欧美国产日产一区二区 | 国产性生大片免费观看性 | 精品人妻中文字幕有码在线 | 亚洲毛片av日韩av无码 | 男人扒开女人内裤强吻桶进去 | 久久综合色之久久综合 | 国产精品久久久 | 亚洲人成网站在线播放942 | 中文字幕日韩精品一区二区三区 | 宝宝好涨水快流出来免费视频 | 亚洲欧美日韩国产精品一区二区 | 强辱丰满人妻hd中文字幕 | 国产成人无码午夜视频在线观看 | 国产小呦泬泬99精品 | 中文字幕无码av激情不卡 | 亚洲人成人无码网www国产 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 日韩视频 中文字幕 视频一区 | 欧美亚洲日韩国产人成在线播放 | 亚洲理论电影在线观看 | 亚洲无人区一区二区三区 | 日韩无套无码精品 | 99国产欧美久久久精品 | 国产亚洲欧美在线专区 | 天天躁日日躁狠狠躁免费麻豆 | 麻豆果冻传媒2021精品传媒一区下载 | 天堂无码人妻精品一区二区三区 | 亚洲精品一区三区三区在线观看 | 亚洲色www成人永久网址 | 人人妻人人澡人人爽欧美精品 | 亚洲精品午夜国产va久久成人 | 少妇愉情理伦片bd | 狠狠色噜噜狠狠狠狠7777米奇 | 国产精品久久久av久久久 | 日韩人妻系列无码专区 | 亚洲综合无码一区二区三区 | 少妇性荡欲午夜性开放视频剧场 | 999久久久国产精品消防器材 | 国产suv精品一区二区五 | 久激情内射婷内射蜜桃人妖 | 荫蒂被男人添的好舒服爽免费视频 | 亚洲精品综合一区二区三区在线 | 亚洲中文字幕无码中字 | 性欧美熟妇videofreesex | 精品无码国产一区二区三区av | 午夜无码区在线观看 | 狠狠综合久久久久综合网 | 久久人人爽人人人人片 | 欧美国产日韩久久mv | 狠狠cao日日穞夜夜穞av | www一区二区www免费 | 天堂а√在线中文在线 | 丰满人妻一区二区三区免费视频 | 久久亚洲精品成人无码 | 乱人伦中文视频在线观看 | 国产精品美女久久久久av爽李琼 | 噜噜噜亚洲色成人网站 | 亚洲区小说区激情区图片区 | 久久综合激激的五月天 | 精品无人区无码乱码毛片国产 | 麻豆果冻传媒2021精品传媒一区下载 | 国产精品久久久久7777 | 亚洲国产av美女网站 | 亚洲s码欧洲m码国产av | 国产69精品久久久久app下载 | 精品国产麻豆免费人成网站 | 男女作爱免费网站 | 欧美日韩色另类综合 | 黄网在线观看免费网站 | 男女下面进入的视频免费午夜 | 午夜男女很黄的视频 | 国产内射爽爽大片视频社区在线 | 国产乱子伦视频在线播放 | 亚洲热妇无码av在线播放 | a在线观看免费网站大全 | 国产乱码精品一品二品 | 丰满人妻被黑人猛烈进入 | 天堂久久天堂av色综合 | 国産精品久久久久久久 | 欧美人与善在线com | 亚洲欧洲日本综合aⅴ在线 | 国语精品一区二区三区 | 亚洲中文字幕乱码av波多ji | 人妻少妇精品无码专区二区 | 永久黄网站色视频免费直播 | 大地资源网第二页免费观看 | 久久97精品久久久久久久不卡 | 日产精品99久久久久久 | 老太婆性杂交欧美肥老太 | 国产免费久久精品国产传媒 | 中文字幕人成乱码熟女app | 无遮挡国产高潮视频免费观看 | 国产精品美女久久久 | yw尤物av无码国产在线观看 | 国产人妻大战黑人第1集 | 超碰97人人射妻 | 国内精品久久毛片一区二区 | 我要看www免费看插插视频 | 领导边摸边吃奶边做爽在线观看 | 国产精品无码一区二区桃花视频 | 久久精品丝袜高跟鞋 | 亚洲精品久久久久avwww潮水 | 丰满少妇女裸体bbw | 黑人粗大猛烈进出高潮视频 | 免费国产成人高清在线观看网站 | 亚洲成在人网站无码天堂 | 国产小呦泬泬99精品 | 国内综合精品午夜久久资源 | 欧美精品一区二区精品久久 | 国产精品久久久久影院嫩草 | 欧美丰满老熟妇xxxxx性 | 对白脏话肉麻粗话av | 日韩无码专区 | 免费网站看v片在线18禁无码 | 亚洲区欧美区综合区自拍区 | 丝袜足控一区二区三区 | 国产成人精品优优av | 久久久久se色偷偷亚洲精品av | 国产成人无码一二三区视频 | 国产片av国语在线观看 | 成人一在线视频日韩国产 | 亚洲成av人片天堂网无码】 | 精品日本一区二区三区在线观看 | 中文字幕无码免费久久9一区9 | 国产精品久久久久久亚洲毛片 | 76少妇精品导航 | 久热国产vs视频在线观看 | 免费无码的av片在线观看 | 无码播放一区二区三区 | 97无码免费人妻超级碰碰夜夜 | 国产又爽又黄又刺激的视频 | 中文字幕乱码人妻无码久久 | 亚洲第一网站男人都懂 | 一本无码人妻在中文字幕免费 | 欧美性猛交内射兽交老熟妇 | 国产疯狂伦交大片 | 国产精品美女久久久 | 欧美人与禽zoz0性伦交 | 欧美xxxx黑人又粗又长 | 久久99久久99精品中文字幕 | 少妇人妻av毛片在线看 | 亚洲国产精品一区二区第一页 | 99麻豆久久久国产精品免费 | 国产三级精品三级男人的天堂 | 欧洲熟妇精品视频 | 欧美日韩在线亚洲综合国产人 | 亚拍精品一区二区三区探花 | 人妻尝试又大又粗久久 | 国精产品一区二区三区 | 激情国产av做激情国产爱 | 波多野42部无码喷潮在线 | 亚洲 日韩 欧美 成人 在线观看 | 日本高清一区免费中文视频 | 精品乱子伦一区二区三区 | 亚洲精品成a人在线观看 | 综合人妻久久一区二区精品 | 亚洲色欲色欲天天天www | 欧洲欧美人成视频在线 | 草草网站影院白丝内射 | 中文精品久久久久人妻不卡 | 亚洲伊人久久精品影院 | 国产成人无码av在线影院 | 中文字幕无码av激情不卡 | 老司机亚洲精品影院 | aⅴ亚洲 日韩 色 图网站 播放 | 性啪啪chinese东北女人 | 国产无av码在线观看 | 国产一区二区三区影院 | 荫蒂被男人添的好舒服爽免费视频 | 无码av免费一区二区三区试看 | 久久午夜无码鲁丝片午夜精品 | 夜先锋av资源网站 | 少妇性l交大片欧洲热妇乱xxx | 亚洲欧洲中文日韩av乱码 | 国精产品一区二区三区 | 成人免费无码大片a毛片 | 久久久久99精品成人片 | 国产高清不卡无码视频 | 国产精品永久免费视频 | 国产精品无码成人午夜电影 | 狠狠色色综合网站 | 久久精品中文字幕一区 | 无套内射视频囯产 | 99精品视频在线观看免费 | 国产成人精品必看 | 伊人久久大香线蕉午夜 | 国产成人无码区免费内射一片色欲 | www成人国产高清内射 | 亚洲精品无码国产 | 国产在线精品一区二区高清不卡 | 国产成人精品优优av | 国产明星裸体无码xxxx视频 | 欧美国产日韩亚洲中文 | 国产电影无码午夜在线播放 | 精品一区二区不卡无码av | 女人被爽到呻吟gif动态图视看 | 国产精品亚洲五月天高清 | 九月婷婷人人澡人人添人人爽 | 一区二区三区乱码在线 | 欧洲 | 欧美激情一区二区三区成人 | 久久久久久久久蜜桃 | 日本熟妇乱子伦xxxx | 国产精品久久久久无码av色戒 | 久久精品国产日本波多野结衣 | 国产精品永久免费视频 | 伊人色综合久久天天小片 | 无遮无挡爽爽免费视频 | 国产69精品久久久久app下载 | 午夜肉伦伦影院 | 免费看男女做好爽好硬视频 | 国精产品一区二区三区 | 国产精品第一国产精品 | 亚无码乱人伦一区二区 | 色综合视频一区二区三区 | 日本饥渴人妻欲求不满 | 天海翼激烈高潮到腰振不止 | 在线天堂新版最新版在线8 | 中文字幕+乱码+中文字幕一区 | 色情久久久av熟女人妻网站 | 国内揄拍国内精品少妇国语 | 一个人看的www免费视频在线观看 | 久久99精品国产麻豆蜜芽 | 成人亚洲精品久久久久 | 国产亚洲人成a在线v网站 | 老太婆性杂交欧美肥老太 | 天堂а√在线地址中文在线 | 欧美日本免费一区二区三区 | 最新版天堂资源中文官网 | 亚洲精品一区二区三区大桥未久 | 自拍偷自拍亚洲精品被多人伦好爽 | 国产精品人人爽人人做我的可爱 | 蜜臀av在线播放 久久综合激激的五月天 | 高潮喷水的毛片 | 精品人妻人人做人人爽夜夜爽 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 97久久国产亚洲精品超碰热 | 国产精品va在线播放 | 久久人人爽人人爽人人片av高清 | 亚洲国精产品一二二线 | 中文字幕无码人妻少妇免费 | 久久综合给合久久狠狠狠97色 | 一本色道久久综合亚洲精品不卡 | 日韩av激情在线观看 | 国产精品无码mv在线观看 | 免费无码肉片在线观看 | 在线欧美精品一区二区三区 | 国产特级毛片aaaaaa高潮流水 | 国产成人精品优优av | 亚洲精品一区二区三区在线 | 亚洲国产日韩a在线播放 | 国产成人综合在线女婷五月99播放 | 女人高潮内射99精品 | 任你躁国产自任一区二区三区 | 人人妻人人澡人人爽人人精品浪潮 | 国产真人无遮挡作爱免费视频 | 国产av剧情md精品麻豆 | 在线播放无码字幕亚洲 | 又大又紧又粉嫩18p少妇 | 日韩人妻无码一区二区三区久久99 | 啦啦啦www在线观看免费视频 | 无码国产色欲xxxxx视频 | 美女黄网站人色视频免费国产 | 色婷婷av一区二区三区之红樱桃 | 久久综合给久久狠狠97色 | 亚洲国产精华液网站w | 国产成人午夜福利在线播放 | 精品久久综合1区2区3区激情 | 久久成人a毛片免费观看网站 | 亚洲精品无码人妻无码 | 国产婷婷色一区二区三区在线 | 免费无码的av片在线观看 | 国产美女精品一区二区三区 | 日韩少妇内射免费播放 | 无码国模国产在线观看 | 日韩人妻少妇一区二区三区 | 精品欧洲av无码一区二区三区 | 无码吃奶揉捏奶头高潮视频 | 激情国产av做激情国产爱 | 亚洲天堂2017无码中文 | 强伦人妻一区二区三区视频18 | 欧美黑人性暴力猛交喷水 | 成人无码精品1区2区3区免费看 | 色噜噜亚洲男人的天堂 | √8天堂资源地址中文在线 | 天天摸天天透天天添 | 亚洲の无码国产の无码影院 | 美女扒开屁股让男人桶 | 欧美真人作爱免费视频 | 永久免费观看美女裸体的网站 | 成人免费视频视频在线观看 免费 | a国产一区二区免费入口 | 粗大的内捧猛烈进出视频 | 在线亚洲高清揄拍自拍一品区 | 亚洲春色在线视频 | 日本乱人伦片中文三区 | 久久久久久久人妻无码中文字幕爆 | 人人妻人人澡人人爽欧美一区 | 国产又爽又黄又刺激的视频 | 精品久久久久久人妻无码中文字幕 | 久久精品人妻少妇一区二区三区 | 欧美性猛交内射兽交老熟妇 | 学生妹亚洲一区二区 | 少妇激情av一区二区 | 国产97在线 | 亚洲 | 青草视频在线播放 | 色综合久久88色综合天天 | 亚洲一区二区三区香蕉 | 国产精品无套呻吟在线 | 无码人妻精品一区二区三区不卡 | 一本久久a久久精品亚洲 | 一本久久a久久精品vr综合 | 中文无码成人免费视频在线观看 | 欧美精品在线观看 | 狠狠色欧美亚洲狠狠色www | 久久久久久国产精品无码下载 | 麻豆成人精品国产免费 | 4hu四虎永久在线观看 | 成熟妇人a片免费看网站 | 人人爽人人爽人人片av亚洲 | 国产99久久精品一区二区 | 在线播放亚洲第一字幕 | 亚洲精品成人福利网站 | 日本丰满护士爆乳xxxx | 成人欧美一区二区三区黑人 | 欧美精品一区二区精品久久 | 亚洲自偷精品视频自拍 | 5858s亚洲色大成网站www | 丰满少妇弄高潮了www | 激情国产av做激情国产爱 | 99riav国产精品视频 | 亚洲成av人在线观看网址 | 四虎国产精品免费久久 | 99精品国产综合久久久久五月天 | 久青草影院在线观看国产 | 麻豆精品国产精华精华液好用吗 | 久久精品国产99精品亚洲 | 狠狠色噜噜狠狠狠狠7777米奇 | 国产精品丝袜黑色高跟鞋 | 5858s亚洲色大成网站www | 欧美刺激性大交 | 国产精品视频免费播放 | 国产性生交xxxxx无码 | 亚洲gv猛男gv无码男同 | 麻豆国产人妻欲求不满 | 中文字幕日产无线码一区 | 免费男性肉肉影院 | 亚洲一区二区三区香蕉 | 欧美老妇与禽交 | 在线欧美精品一区二区三区 | 日本肉体xxxx裸交 | 婷婷综合久久中文字幕蜜桃三电影 | 日本乱人伦片中文三区 | 未满小14洗澡无码视频网站 | 欧美放荡的少妇 | 少妇激情av一区二区 | 国产成人一区二区三区别 | 中文字幕亚洲情99在线 | 成人欧美一区二区三区 | 欧美性猛交内射兽交老熟妇 | 亚洲乱亚洲乱妇50p | 国产精品亚洲一区二区三区喷水 | 久久精品人妻少妇一区二区三区 | 国产人妻人伦精品1国产丝袜 | 亚洲人交乣女bbw | 永久免费观看美女裸体的网站 | 国产成人无码a区在线观看视频app | 国产凸凹视频一区二区 | 日本在线高清不卡免费播放 | 波多野结衣 黑人 | 夜夜夜高潮夜夜爽夜夜爰爰 | 377p欧洲日本亚洲大胆 | 天干天干啦夜天干天2017 | 樱花草在线播放免费中文 | 免费无码肉片在线观看 | 国产两女互慰高潮视频在线观看 | 又大又硬又爽免费视频 | 亚洲精品一区二区三区在线观看 | 亚洲欧美日韩国产精品一区二区 | 极品尤物被啪到呻吟喷水 | 国产精品久久久久影院嫩草 | 亚拍精品一区二区三区探花 | 久久精品人人做人人综合试看 | 欧美日韩亚洲国产精品 | 娇妻被黑人粗大高潮白浆 | 波多野结衣aⅴ在线 | 国产乱人伦偷精品视频 | 色一情一乱一伦一区二区三欧美 | av在线亚洲欧洲日产一区二区 | 2020久久超碰国产精品最新 | 国产乱人伦偷精品视频 | 国产香蕉尹人综合在线观看 | 中文字幕精品av一区二区五区 | 亚洲娇小与黑人巨大交 | 一本久久伊人热热精品中文字幕 | 在线а√天堂中文官网 | 亚洲综合在线一区二区三区 | 欧美精品免费观看二区 | 特级做a爰片毛片免费69 | 精品国产一区二区三区av 性色 | 性欧美熟妇videofreesex | 无遮挡啪啪摇乳动态图 | 久热国产vs视频在线观看 | 色欲av亚洲一区无码少妇 | 东京一本一道一二三区 | 又粗又大又硬又长又爽 | 亚洲熟妇色xxxxx欧美老妇 | 最新版天堂资源中文官网 | 色欲综合久久中文字幕网 | 国产97色在线 | 免 | 亚洲成av人片在线观看无码不卡 | 国产人成高清在线视频99最全资源 | 日本xxxx色视频在线观看免费 | 国产9 9在线 | 中文 | 国产精品久久久久久亚洲毛片 | 亚洲高清偷拍一区二区三区 | 亚洲 激情 小说 另类 欧美 | 狠狠色噜噜狠狠狠狠7777米奇 | 正在播放老肥熟妇露脸 | 成人无码精品一区二区三区 | 国产精品va在线观看无码 | 99riav国产精品视频 | 亚洲国产一区二区三区在线观看 | 国产精品久久久久9999小说 | 乱码午夜-极国产极内射 | 亚洲а∨天堂久久精品2021 | 国产精品久免费的黄网站 | 精品久久久久久人妻无码中文字幕 | 国内精品久久毛片一区二区 | 99久久精品日本一区二区免费 | 人人妻人人澡人人爽人人精品 | 99久久精品国产一区二区蜜芽 | 四十如虎的丰满熟妇啪啪 | 久久综合久久自在自线精品自 | 欧美性猛交内射兽交老熟妇 | 国产精品久久国产三级国 | 欧美zoozzooz性欧美 | 日本精品高清一区二区 | 人妻无码αv中文字幕久久琪琪布 | 97久久国产亚洲精品超碰热 | 亚洲欧美日韩综合久久久 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 国产精品理论片在线观看 | 四虎影视成人永久免费观看视频 | 久久精品女人的天堂av | 国内老熟妇对白xxxxhd | 亚洲国产精品久久人人爱 | 欧美日韩一区二区综合 | 蜜臀av在线观看 在线欧美精品一区二区三区 | 人人澡人人透人人爽 | 日韩人妻无码一区二区三区久久99 | 亚洲gv猛男gv无码男同 | 精品亚洲成av人在线观看 | a在线观看免费网站大全 | 少妇被黑人到高潮喷出白浆 | 欧美丰满熟妇xxxx性ppx人交 | 日本一本二本三区免费 | 中文字幕av伊人av无码av | 一本久道久久综合狠狠爱 | 中文字幕人妻无码一区二区三区 | 亚洲精品午夜国产va久久成人 | 欧美老人巨大xxxx做受 | 少妇愉情理伦片bd | 免费国产黄网站在线观看 | 久久综合给久久狠狠97色 | 国产人妻人伦精品1国产丝袜 | 国产精品成人av在线观看 | 小sao货水好多真紧h无码视频 | 无遮挡啪啪摇乳动态图 | 中文字幕av日韩精品一区二区 | 又粗又大又硬又长又爽 | 久久国语露脸国产精品电影 | 美女扒开屁股让男人桶 | 欧美黑人巨大xxxxx | 亚洲爆乳精品无码一区二区三区 | 熟妇人妻无码xxx视频 | 麻豆国产人妻欲求不满 | 狂野欧美性猛交免费视频 | 最新国产乱人伦偷精品免费网站 | 精品厕所偷拍各类美女tp嘘嘘 | 国产乱码精品一品二品 | 午夜时刻免费入口 | 日本精品高清一区二区 | 午夜不卡av免费 一本久久a久久精品vr综合 | 午夜精品一区二区三区的区别 | 亚洲日韩av一区二区三区四区 | 麻豆果冻传媒2021精品传媒一区下载 | 男女下面进入的视频免费午夜 | 四虎国产精品一区二区 | 久久婷婷五月综合色国产香蕉 | 日产精品99久久久久久 | 人人妻人人澡人人爽精品欧美 | 噜噜噜亚洲色成人网站 | 夜夜夜高潮夜夜爽夜夜爰爰 | 国产av剧情md精品麻豆 | 给我免费的视频在线观看 | 色一情一乱一伦一视频免费看 | 一本大道久久东京热无码av | 天堂无码人妻精品一区二区三区 | 丰满少妇女裸体bbw | 老司机亚洲精品影院无码 | 少妇激情av一区二区 | 欧美 日韩 人妻 高清 中文 | 曰韩无码二三区中文字幕 | 色一情一乱一伦一区二区三欧美 | 激情内射日本一区二区三区 | 西西人体www44rt大胆高清 | 好屌草这里只有精品 | 色综合天天综合狠狠爱 | 日本乱人伦片中文三区 | 综合网日日天干夜夜久久 | 久久久久国色av免费观看性色 | 免费无码午夜福利片69 | 国产激情艳情在线看视频 | 97无码免费人妻超级碰碰夜夜 | 亚洲成av人影院在线观看 | 内射欧美老妇wbb | 国产凸凹视频一区二区 | 国内精品久久久久久中文字幕 | 麻豆国产人妻欲求不满谁演的 | 99视频精品全部免费免费观看 | 国产无遮挡吃胸膜奶免费看 | 国产凸凹视频一区二区 | 乌克兰少妇性做爰 | 九九在线中文字幕无码 | 精品午夜福利在线观看 | 老熟女乱子伦 | 亚洲男人av天堂午夜在 | 老头边吃奶边弄进去呻吟 | 狠狠躁日日躁夜夜躁2020 | 无码精品国产va在线观看dvd | 高中生自慰www网站 | 国内精品九九久久久精品 | 最新国产乱人伦偷精品免费网站 | 中文字幕 人妻熟女 | 一区二区传媒有限公司 | 99视频精品全部免费免费观看 | 国产激情精品一区二区三区 | 熟女体下毛毛黑森林 | 成年美女黄网站色大免费视频 | 亚洲小说图区综合在线 | 日欧一片内射va在线影院 | 樱花草在线社区www | 久久综合网欧美色妞网 | 国产亲子乱弄免费视频 | 一二三四社区在线中文视频 | 天天燥日日燥 | 蜜臀aⅴ国产精品久久久国产老师 | 亚洲区小说区激情区图片区 | 大地资源网第二页免费观看 | 中文无码伦av中文字幕 | 东京一本一道一二三区 | 精品国产青草久久久久福利 | 野外少妇愉情中文字幕 | 麻豆国产人妻欲求不满 | 国产极品美女高潮无套在线观看 | 免费男性肉肉影院 | 国内揄拍国内精品人妻 | 国产精品久久久久无码av色戒 | 亚洲国精产品一二二线 | 99riav国产精品视频 | 一本大道久久东京热无码av | 欧美日韩视频无码一区二区三 | 日产精品高潮呻吟av久久 | 精品亚洲成av人在线观看 | 亚洲娇小与黑人巨大交 | 亚洲欧洲日本综合aⅴ在线 | 丁香啪啪综合成人亚洲 | 99久久人妻精品免费二区 | 国产 精品 自在自线 | 樱花草在线播放免费中文 | 黑人粗大猛烈进出高潮视频 | 国产莉萝无码av在线播放 | 亚洲精品成a人在线观看 | 午夜时刻免费入口 | 久久国产36精品色熟妇 | 国产sm调教视频在线观看 | 大肉大捧一进一出好爽视频 | 亚洲成av人在线观看网址 | 国产亚洲视频中文字幕97精品 | 亚洲另类伦春色综合小说 | 免费人成网站视频在线观看 | 97精品人妻一区二区三区香蕉 | 人人妻人人藻人人爽欧美一区 | 伦伦影院午夜理论片 | 亚洲国产成人av在线观看 | 波多野结衣高清一区二区三区 | 人妻插b视频一区二区三区 | 亚欧洲精品在线视频免费观看 | 精品人妻人人做人人爽 | 最近中文2019字幕第二页 | 欧美丰满熟妇xxxx性ppx人交 | 天下第一社区视频www日本 | 久久国内精品自在自线 | 俺去俺来也www色官网 | 无人区乱码一区二区三区 | 无码任你躁久久久久久久 | 国产成人无码午夜视频在线观看 | 精品无码国产一区二区三区av | 日韩视频 中文字幕 视频一区 | 日日鲁鲁鲁夜夜爽爽狠狠 | 丰满妇女强制高潮18xxxx | 东京热一精品无码av | 伊人久久大香线蕉av一区二区 | 国产亚洲精品久久久久久久 | 亚洲国产一区二区三区在线观看 | 中文字幕无码日韩专区 | 中文字幕av伊人av无码av | 亚洲精品成人福利网站 | 久久亚洲中文字幕精品一区 | 午夜无码区在线观看 | 色一情一乱一伦一区二区三欧美 | 亚欧洲精品在线视频免费观看 | 国语自产偷拍精品视频偷 | 亚洲成a人片在线观看日本 | 最新国产乱人伦偷精品免费网站 | 丝袜 中出 制服 人妻 美腿 | 国产精品成人av在线观看 | 亚洲色大成网站www | 久久久久人妻一区精品色欧美 | 无码人妻av免费一区二区三区 | 少妇性l交大片欧洲热妇乱xxx | 国产精品无码永久免费888 | 亚洲熟妇色xxxxx欧美老妇y | 色欲人妻aaaaaaa无码 | 奇米影视888欧美在线观看 | 亚洲成色在线综合网站 | 亚洲码国产精品高潮在线 | 理论片87福利理论电影 | 亚洲国产精品一区二区美利坚 | 日韩人妻少妇一区二区三区 | 国产婷婷色一区二区三区在线 | 国产无遮挡吃胸膜奶免费看 | 性色欲情网站iwww九文堂 | 一本大道久久东京热无码av | 丰满人妻一区二区三区免费视频 | 欧美高清在线精品一区 | 无码人妻久久一区二区三区不卡 | 永久免费精品精品永久-夜色 | 久久精品国产一区二区三区肥胖 | 蜜桃av抽搐高潮一区二区 | 国产亚洲欧美在线专区 | 免费无码肉片在线观看 | 伊人久久婷婷五月综合97色 | 精品一二三区久久aaa片 | 久久婷婷五月综合色国产香蕉 | 成人欧美一区二区三区黑人免费 | 亚洲国产午夜精品理论片 | 一二三四社区在线中文视频 | 国精产品一品二品国精品69xx | 国产亚洲美女精品久久久2020 | 国产av一区二区三区最新精品 | 免费人成在线观看网站 | 男人的天堂2018无码 | 一本久道久久综合狠狠爱 | 无码任你躁久久久久久久 | 国产精品办公室沙发 | 丝袜美腿亚洲一区二区 | 亚洲中文字幕在线无码一区二区 | 国产69精品久久久久app下载 | 成人av无码一区二区三区 | 国产av人人夜夜澡人人爽麻豆 | 97se亚洲精品一区 | 国产午夜视频在线观看 | 欧洲极品少妇 | 无码人妻精品一区二区三区下载 | 色狠狠av一区二区三区 | 久久97精品久久久久久久不卡 | 老头边吃奶边弄进去呻吟 | 亚洲熟妇自偷自拍另类 | 国产农村乱对白刺激视频 | 成人一区二区免费视频 | 欧美xxxx黑人又粗又长 | 欧美性猛交xxxx富婆 | 未满成年国产在线观看 | 无套内射视频囯产 | 精品熟女少妇av免费观看 | 青青草原综合久久大伊人精品 | 欧美老人巨大xxxx做受 | 日本成熟视频免费视频 | 亚洲の无码国产の无码步美 | 人妻无码αv中文字幕久久琪琪布 | 国产色xx群视频射精 | 中文字幕人成乱码熟女app | av香港经典三级级 在线 | 亚洲熟女一区二区三区 | 麻豆人妻少妇精品无码专区 | 99久久人妻精品免费一区 | 久久 国产 尿 小便 嘘嘘 | 色诱久久久久综合网ywww | 亚洲综合无码久久精品综合 | 中文字幕乱码亚洲无线三区 | 国产精品久久国产三级国 | 在线播放免费人成毛片乱码 | 欧美性猛交xxxx富婆 | 在线观看欧美一区二区三区 | 国产精品18久久久久久麻辣 | 午夜精品一区二区三区的区别 | 亚洲精品中文字幕久久久久 | 色妞www精品免费视频 | 婷婷综合久久中文字幕蜜桃三电影 | 久久人人爽人人人人片 | 国产亚洲tv在线观看 | 国产成人综合色在线观看网站 | 欧美猛少妇色xxxxx | 18禁黄网站男男禁片免费观看 | 国产精品人人爽人人做我的可爱 | 一本久久a久久精品亚洲 | 99久久99久久免费精品蜜桃 | 最近的中文字幕在线看视频 | av小次郎收藏 | 精品人妻中文字幕有码在线 | 亚洲色成人中文字幕网站 | 国产熟女一区二区三区四区五区 | 少妇无码一区二区二三区 | 久久久中文字幕日本无吗 | 国产麻豆精品精东影业av网站 | 天干天干啦夜天干天2017 | 久热国产vs视频在线观看 | 久久精品中文闷骚内射 | 青草青草久热国产精品 | 国产成人亚洲综合无码 | 国产偷国产偷精品高清尤物 | 成人片黄网站色大片免费观看 | 欧美乱妇无乱码大黄a片 | 亚洲精品一区三区三区在线观看 | 亚洲精品综合一区二区三区在线 | 丝袜人妻一区二区三区 | 国产精品久久国产三级国 | 老太婆性杂交欧美肥老太 | 亚洲欧美日韩国产精品一区二区 | 麻豆国产丝袜白领秘书在线观看 | 国产特级毛片aaaaaaa高清 | 亚洲人成影院在线观看 | 国产又爽又黄又刺激的视频 | 欧美性猛交xxxx富婆 | 四虎4hu永久免费 | 国产精品高潮呻吟av久久 | 白嫩日本少妇做爰 | 亚洲男人av天堂午夜在 | 国产亚洲人成在线播放 | 国产超级va在线观看视频 | 成人免费视频一区二区 | 日日鲁鲁鲁夜夜爽爽狠狠 | 国产激情一区二区三区 | 又色又爽又黄的美女裸体网站 | 精品无码av一区二区三区 | 兔费看少妇性l交大片免费 | 国产精品视频免费播放 | 无码中文字幕色专区 | 久久午夜无码鲁丝片 | 中文精品久久久久人妻不卡 | 亚洲欧美国产精品专区久久 | 亚洲精品成人av在线 | 成 人 网 站国产免费观看 | 正在播放东北夫妻内射 | 男女作爱免费网站 | 色欲久久久天天天综合网精品 | 日韩精品无码一区二区中文字幕 | 99国产欧美久久久精品 | 精品亚洲成av人在线观看 | 久久熟妇人妻午夜寂寞影院 | 亚洲精品久久久久久久久久久 | 国产无遮挡又黄又爽免费视频 | 免费人成在线观看网站 | 丰满肥臀大屁股熟妇激情视频 | 东京热一精品无码av | 久久天天躁狠狠躁夜夜免费观看 | 国产舌乚八伦偷品w中 | 亚洲色欲色欲欲www在线 | 中文字幕乱码亚洲无线三区 | 丝袜 中出 制服 人妻 美腿 | 国产农村乱对白刺激视频 | 搡女人真爽免费视频大全 | 无码人妻久久一区二区三区不卡 | 色婷婷久久一区二区三区麻豆 | 日韩成人一区二区三区在线观看 | 亚洲va中文字幕无码久久不卡 | 大肉大捧一进一出好爽视频 | 亚洲大尺度无码无码专区 | 久久国产精品萌白酱免费 | 亚欧洲精品在线视频免费观看 | 日日碰狠狠躁久久躁蜜桃 | 国产亚洲精品久久久久久大师 | 日韩人妻系列无码专区 | 色欲av亚洲一区无码少妇 | 人妻无码久久精品人妻 | av小次郎收藏 | 99精品久久毛片a片 | 欧美精品无码一区二区三区 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 国产精品免费大片 | 东京一本一道一二三区 | 无码人妻黑人中文字幕 | 国产国产精品人在线视 | 野狼第一精品社区 | аⅴ资源天堂资源库在线 | 妺妺窝人体色www在线小说 | 欧美 日韩 人妻 高清 中文 | 亚洲精品中文字幕 | 九九综合va免费看 | 天天爽夜夜爽夜夜爽 | 成人精品天堂一区二区三区 | 国语自产偷拍精品视频偷 | 亚洲精品国产第一综合99久久 | 国产午夜精品一区二区三区嫩草 | 无码国内精品人妻少妇 | 国产在线精品一区二区高清不卡 | 日韩人妻系列无码专区 | 99久久精品国产一区二区蜜芽 | 欧美人与动性行为视频 | 国产热a欧美热a在线视频 | 强伦人妻一区二区三区视频18 | 国产精品高潮呻吟av久久4虎 | 丰满人妻翻云覆雨呻吟视频 | 国产成人无码专区 | 国产成人无码a区在线观看视频app | 日韩欧美群交p片內射中文 | 一二三四在线观看免费视频 | 天堂а√在线中文在线 | 99精品久久毛片a片 | 熟妇人妻无乱码中文字幕 | 久久亚洲国产成人精品性色 | 久久久久久久女国产乱让韩 | 初尝人妻少妇中文字幕 | 国产精品亚洲专区无码不卡 | 国产精品怡红院永久免费 | 久久综合狠狠综合久久综合88 | 成人免费视频视频在线观看 免费 | 亚洲国产精华液网站w | 丰满人妻精品国产99aⅴ | 少妇无码一区二区二三区 | 中文字幕无线码 | 日韩精品无码一区二区中文字幕 | 无码av岛国片在线播放 | 国产精品多人p群无码 | 曰韩无码二三区中文字幕 | 激情五月综合色婷婷一区二区 | 1000部夫妻午夜免费 | 内射老妇bbwx0c0ck | 亚洲无人区午夜福利码高清完整版 | aⅴ在线视频男人的天堂 | 精品国产一区二区三区av 性色 | 天天躁日日躁狠狠躁免费麻豆 | 蜜臀aⅴ国产精品久久久国产老师 | 欧美怡红院免费全部视频 | 国产亚洲精品精品国产亚洲综合 | 无码av岛国片在线播放 | www国产亚洲精品久久网站 | 久久久国产一区二区三区 | 久久久国产一区二区三区 | 少妇被黑人到高潮喷出白浆 | 东京热无码av男人的天堂 | 十八禁真人啪啪免费网站 | 六十路熟妇乱子伦 | 熟妇人妻无乱码中文字幕 | 三上悠亚人妻中文字幕在线 | aⅴ亚洲 日韩 色 图网站 播放 | 日韩人妻少妇一区二区三区 | 香蕉久久久久久av成人 | 国内少妇偷人精品视频 | 日本高清一区免费中文视频 | 国产在热线精品视频 | 久久婷婷五月综合色国产香蕉 | 亚洲成熟女人毛毛耸耸多 | 1000部夫妻午夜免费 | 色诱久久久久综合网ywww | 国产色精品久久人妻 | 欧美肥老太牲交大战 | 精品午夜福利在线观看 | 一区二区三区乱码在线 | 欧洲 | 人妻互换免费中文字幕 | 精品无码一区二区三区爱欲 | 国产亚洲精品久久久久久久 | 国内老熟妇对白xxxxhd | aⅴ在线视频男人的天堂 | 亚洲日韩精品欧美一区二区 | 国色天香社区在线视频 | 欧美激情综合亚洲一二区 | 人人澡人人妻人人爽人人蜜桃 | 波多野结衣乳巨码无在线观看 | 久久午夜夜伦鲁鲁片无码免费 | 骚片av蜜桃精品一区 | 狠狠色噜噜狠狠狠7777奇米 | 国产日产欧产精品精品app | 一二三四社区在线中文视频 | 亚洲 另类 在线 欧美 制服 | 在线播放无码字幕亚洲 | 中文字幕+乱码+中文字幕一区 | 日韩精品无码一本二本三本色 | 久久久久99精品成人片 |