国产精品青草久-国产精品情侣愉拍-国产精品区网红主-国产精品区一区二-国产精品热久久-国产精品热热热-国产精品人aⅴ-国产精品人成在线-国产精品人妻人伦-国产精品人人

金喜正规买球

logo 移動(dòng)開發(fā)學(xué)習(xí)指南

文檔金喜正規(guī)買球>>移動(dòng)開發(fā)學(xué)習(xí)指南>>Xamarin Forms的Prism第二部分:基本導(dǎo)航和依賴注入(Dependency Injection)模式

Xamarin Forms的Prism第二部分:基本導(dǎo)航和依賴注入(Dependency Injection)模式


前一篇文章中,我們已經(jīng)開始介紹在Xamarin Forms應(yīng)用程序中如何利用Prism(6.2)的新版本來實(shí)現(xiàn)MVVM模式的基本概念。到目前為止,我們還沒有看到什么特別的東西是我們用另一個(gè)框架做不到的:我們在上一篇文章中創(chuàng)建了一個(gè)視圖(View)、一個(gè)視圖模型(ViewModel),然后我們通過綁定連接它們。在這篇文章中,我們將看到Prism如何幫助處理一個(gè)在MVVM應(yīng)用程序中很難處理的非常常見的場景:導(dǎo)航和頁面的生命周期。

Xamarin Forms的Prism第二部分:基本導(dǎo)航和依賴注入(Dependency Injection)模式

正如我們在前一篇文章中提到的,我們要為TrackSeries——一個(gè)提供電視節(jié)目信息的網(wǎng)站,創(chuàng)建一個(gè)簡單的客戶端。該應(yīng)用程序?qū)@示當(dāng)前的頂級系列,將允許用戶發(fā)現(xiàn)更多關(guān)于它的內(nèi)容。為了實(shí)現(xiàn)這一目標(biāo),我們可以用一組網(wǎng)站提供的REST服務(wù),這是非常簡單的使用和處理REST服務(wù)的遵循標(biāo)準(zhǔn)的最佳實(shí)踐:你調(diào)用一個(gè)使用HTTP命令的URL,接收返回一個(gè)JSON響應(yīng)結(jié)果。

舉個(gè)例子,如果你想知道哪些是頂級系列,你可以執(zhí)行一個(gè)HTTP GET請求到以下URL:。服務(wù)將返回給你一個(gè)JSON響應(yīng),包含頂級系列的所有細(xì)節(jié):

[
   {
      "id":121361,
      "name":"Game of Thrones",
      "followers":10230,
      "firstAired":"2011-04-17T21:00:00-04:00",
      "country":"us",
      "overview":"Seven noble families fight for control of the mythical land of Westeros. Friction between the houses leads to full-scale war. All while a very ancient evil awakens in the farthest north. Amidst the war, a neglected military order of misfits, the Night's Watch, is all that stands between the realms of men and the icy horrors beyond.",
      "runtime":55,
      "status":"Continuing",
      "network":"HBO",
      "airDay":"Sunday",
      "airTime":"9:00 PM",
      "contentRating":"TV-MA",
      "imdbId":"tt0944947",
      "tvdbId":121361,
      "tmdbId":1399,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/121361-49.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/121361-15.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/121361-g22.jpg"
      },
      "genres":[
         {
            "id":2,
            "name":"Adventure"
         },
         {
            "id":4,
            "name":"Drama"
         },
         {
            "id":5,
            "name":"Fantasy"
         }
      ],
      "added":"2014-08-08T13:30:46.227",
      "lastUpdated":"2016-08-18T03:03:50.05",
      "followedByUser":false,
      "slugName":"game-of-thrones"
   },
   {
      "id":257655,
      "name":"Arrow",
      "followers":7517,
      "firstAired":"2012-10-10T20:00:00-04:00",
      "country":"us",
      "overview":"Oliver Queen and his father are lost at sea when their luxury yacht sinks. His father doesn't survive. Oliver survives on an uncharted island for five years learning to fight, but also learning about his father's corruption and unscrupulous business dealings. He returns to civilization a changed man, determined to put things right. He disguises himself with the hood of one of his mysterious island mentors, arms himself with a bow and sets about hunting down the men and women who have corrupted his city.",
      "runtime":45,
      "status":"Continuing",
      "network":"The CW",
      "airDay":"Wednesday",
      "airTime":"8:00 PM",
      "contentRating":"TV-14",
      "imdbId":"tt2193021",
      "tvdbId":257655,
      "tmdbId":1412,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/257655-8.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/257655-47.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/257655-g9.jpg"
      },
      "genres":[
         {
            "id":1,
            "name":"Action"
         },
         {
            "id":2,
            "name":"Adventure"
         },
         {
            "id":4,
            "name":"Drama"
         }
      ],
      "added":"2014-08-08T13:37:00.133",
      "lastUpdated":"2016-08-15T03:11:32.013",
      "followedByUser":false,
      "slugName":"arrow"
   },
   {
      "id":153021,
      "name":"The Walking Dead",
      "followers":7185,
      "firstAired":"2010-10-31T21:00:00-04:00",
      "country":"us",
      "overview":"The world we knew is gone. An epidemic of apocalyptic proportions has swept the globe causing the dead to rise and feed on the living. In a matter of months society has crumbled. In a world ruled by the dead, we are forced to finally start living. Based on a comic book series of the same name by Robert Kirkman, this AMC project focuses on the world after a zombie apocalypse. The series follows a police officer, Rick Grimes, who wakes up from a coma to find the world ravaged with zombies. Looking for his family, he and a group of survivors attempt to battle against the zombies in order to stay alive.\n",
      "runtime":50,
      "status":"Continuing",
      "network":"AMC",
      "airDay":"Sunday",
      "airTime":"9:00 PM",
      "contentRating":"TV-MA",
      "imdbId":"tt1520211",
      "tvdbId":153021,
      "tmdbId":1402,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/153021-38.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/153021-77.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/153021-g44.jpg"
      },
      "genres":[
         {
            "id":1,
            "name":"Action"
         },
         {
            "id":4,
            "name":"Drama"
         },
         {
            "id":6,
            "name":"Horror"
         },
         {
            "id":20,
            "name":"Suspense"
         }
      ],
      "added":"2014-08-08T13:31:18.617",
      "lastUpdated":"2016-08-18T03:04:00.28",
      "followedByUser":false,
      "slugName":"the-walking-dead"
   },
   {
      "id":279121,
      "name":"The Flash (2014)",
      "followers":7069,
      "firstAired":"2014-10-07T20:00:00-04:00",
      "country":"us",
      "overview":"After a particle accelerator causes a freak storm, CSI Investigator Barry Allen is struck by lightning and falls into a coma. Months later he awakens with the power of super speed, granting him the ability to move through Central City like an unseen guardian angel. Though initially excited by his newfound powers, Barry is shocked to discover he is not the only \"meta-human\" who was created in the wake of the accelerator explosion – and not everyone is using their new powers for good. Barry partners with S.T.A.R. Labs and dedicates his life to protect the innocent. For now, only a few close friends and associates know that Barry is literally the fastest man alive, but it won't be long before the world learns what Barry Allen has become... The Flash.",
      "runtime":45,
      "status":"Continuing",
      "network":"The CW",
      "airDay":"Tuesday",
      "airTime":"8:00 PM",
      "contentRating":"TV-14",
      "imdbId":"tt3107288",
      "tvdbId":279121,
      "tmdbId":60735,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/279121-37.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/279121-23.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/279121-g7.jpg"
      },
      "genres":[
         {
            "id":1,
            "name":"Action"
         },
         {
            "id":2,
            "name":"Adventure"
         },
         {
            "id":4,
            "name":"Drama"
         },
         {
            "id":8,
            "name":"Science-Fiction"
         }
      ],
      "added":"2014-08-08T13:45:59.087",
      "lastUpdated":"2016-08-17T03:09:18.7",
      "followedByUser":false,
      "slugName":"the-flash-2014"
   },
   {
      "id":80379,
      "name":"The Big Bang Theory",
      "followers":6922,
      "firstAired":"2007-09-25T20:00:00-04:00",
      "country":"us",
      "overview":"What happens when hyperintelligent roommates Sheldon and Leonard meet Penny, a free-spirited beauty moving in next door, and realize they know next to nothing about life outside of the lab. Rounding out the crew are the smarmy Wolowitz, who thinks he's as sexy as he is brainy, and Koothrappali, who suffers from an inability to speak in the presence of a woman.",
      "runtime":25,
      "status":"Continuing",
      "network":"CBS",
      "airDay":"Monday",
      "airTime":"8:00 PM",
      "contentRating":"TV-PG",
      "imdbId":"tt0898266",
      "tvdbId":80379,
      "tmdbId":1418,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/80379-43.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/80379-38.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/80379-g28.jpg"
      },
      "genres":[
         {
            "id":3,
            "name":"Comedy"
         }
      ],
      "added":"2014-08-08T13:27:13.18",
      "lastUpdated":"2016-08-18T03:03:10.947",
      "followedByUser":false,
      "slugName":"the-big-bang-theory"
   },
   {
      "id":176941,
      "name":"Sherlock",
      "followers":6387,
      "firstAired":"2010-07-25T20:30:00+01:00",
      "country":"gb",
      "overview":"Sherlock is a British television crime drama that presents a contemporary adaptation of Sir Arthur Conan Doyle's Sherlock Holmes detective stories. Created by Steven Moffat and Mark Gatiss, it stars Benedict Cumberbatch as Sherlock Holmes and Martin Freeman as Doctor John Watson.",
      "runtime":90,
      "status":"Continuing",
      "network":"BBC One",
      "airDay":"Sunday",
      "airTime":"8:30 PM",
      "contentRating":"TV-14",
      "imdbId":"tt1475582",
      "tvdbId":176941,
      "tmdbId":19885,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/176941-11.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/176941-3.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/176941-g5.jpg"
      },
      "genres":[
         {
            "id":2,
            "name":"Adventure"
         },
         {
            "id":4,
            "name":"Drama"
         },
         {
            "id":14,
            "name":"Crime"
         },
         {
            "id":16,
            "name":"Mystery"
         },
         {
            "id":21,
            "name":"Thriller"
         }
      ],
      "added":"2014-08-08T13:32:27.247",
      "lastUpdated":"2016-08-17T03:07:09.747",
      "followedByUser":false,
      "slugName":"sherlock"
   },
   {
      "id":263365,
      "name":"Marvel's Agents of S.H.I.E.L.D.",
      "followers":5372,
      "firstAired":"2013-09-24T22:00:00-04:00",
      "country":"us",
      "overview":"Phil Coulson (Clark Gregg, reprising his role from \"The Avengers\" and \"Iron Man\" ) heads an elite team of fellow agents with the worldwide law-enforcement organization known as SHIELD (Strategic Homeland Intervention Enforcement and Logistics Division), as they investigate strange occurrences around the globe. Its members -- each of whom brings a specialty to the group -- work with Coulson to protect those who cannot protect themselves from extraordinary and inconceivable threats, including a formidable group known as Hydra.",
      "runtime":45,
      "status":"Continuing",
      "network":"ABC (US)",
      "airDay":"Tuesday",
      "airTime":"10:00 PM",
      "contentRating":"TV-PG",
      "imdbId":"tt2364582",
      "tvdbId":263365,
      "tmdbId":1403,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/263365-16.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/263365-26.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/263365-g7.jpg"
      },
      "genres":[
         {
            "id":1,
            "name":"Action"
         },
         {
            "id":2,
            "name":"Adventure"
         },
         {
            "id":4,
            "name":"Drama"
         },
         {
            "id":5,
            "name":"Fantasy"
         },
         {
            "id":8,
            "name":"Science-Fiction"
         }
      ],
      "added":"2014-08-08T13:39:45.967",
      "lastUpdated":"2016-08-18T03:05:30.987",
      "followedByUser":false,
      "slugName":"marvels-agents-of-shield"
   },
   {
      "id":81189,
      "name":"Breaking Bad",
      "followers":5227,
      "firstAired":"2008-01-20T21:00:00-04:00",
      "country":"us",
      "overview":"Walter White, a struggling high school chemistry teacher, is diagnosed with advanced lung cancer. He turns to a life of crime, producing and selling methamphetamine accompanied by a former student, Jesse Pinkman, with the aim of securing his family's financial future before he dies.",
      "runtime":45,
      "status":"Ended",
      "network":"AMC",
      "airDay":"Sunday",
      "airTime":"9:00 PM",
      "contentRating":"TV-MA",
      "imdbId":"tt0903747",
      "tvdbId":81189,
      "tmdbId":1396,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/81189-10.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/81189-21.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/81189-g21.jpg"
      },
      "genres":[
         {
            "id":4,
            "name":"Drama"
         },
         {
            "id":14,
            "name":"Crime"
         },
         {
            "id":20,
            "name":"Suspense"
         },
         {
            "id":21,
            "name":"Thriller"
         }
      ],
      "added":"2014-08-08T13:27:33.917",
      "lastUpdated":"2016-08-13T03:01:47.063",
      "followedByUser":false,
      "slugName":"breaking-bad"
   },
   {
      "id":247808,
      "name":"Suits",
      "followers":4835,
      "firstAired":"2011-06-24T21:00:00-04:00",
      "country":"us",
      "overview":"Suits follows college drop-out Mike Ross, who accidentally lands a job with one of New York's best legal closers, Harvey Specter. They soon become a winning team with Mike's raw talent and photographic memory, and Mike soon reminds Harvey of why he went into the field of law in the first place.",
      "runtime":45,
      "status":"Continuing",
      "network":"USA Network",
      "airDay":"Wednesday",
      "airTime":"9:00 PM",
      "contentRating":"TV-14",
      "imdbId":"tt1632701",
      "tvdbId":247808,
      "tmdbId":37680,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/247808-27.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/247808-43.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/247808-g17.jpg"
      },
      "genres":[
         {
            "id":4,
            "name":"Drama"
         }
      ],
      "added":"2014-08-08T13:33:45.423",
      "lastUpdated":"2016-08-18T03:04:21.37",
      "followedByUser":false,
      "slugName":"suits"
   },
   {
      "id":274431,
      "name":"Gotham",
      "followers":4718,
      "firstAired":"2014-09-23T20:00:00-04:00",
      "country":"us",
      "overview":"An action-drama series following rookie detective James Gordon as he battles villains and corruption in pre-Batman Gotham City.",
      "runtime":45,
      "status":"Continuing",
      "network":"FOX (US)",
      "airDay":"Monday",
      "airTime":"8:00 PM",
      "contentRating":"TV-14",
      "imdbId":"tt3749900",
      "tvdbId":274431,
      "tmdbId":60708,
      "language":"en",
      "images":{
         "poster":"//static.trackseries.tv/banners/posters/274431-17.jpg",
         "fanart":"//static.trackseries.tv/banners/fanart/original/274431-22.jpg",
         "banner":"//static.trackseries.tv/banners/graphical/274431-g6.jpg"
      },
      "genres":[
         {
            "id":1,
            "name":"Action"
         },
         {
            "id":4,
            "name":"Drama"
         },
         {
            "id":8,
            "name":"Science-Fiction"
         },
         {
            "id":14,
            "name":"Crime"
         },
         {
            "id":21,
            "name":"Thriller"
         }
      ],
      "added":"2014-08-08T13:44:55.4",
      "lastUpdated":"2016-08-17T03:08:55.473",
      "followedByUser":false,
      "slugName":"gotham"
   }
]

為了使用這些應(yīng)用程序中的API,我用一組方法創(chuàng)建了一個(gè)稱為TsApiService的類,通過.NET框架和流行的JSON.NET庫的HttpClient類,負(fù)責(zé)下載JSON,解析它并返回一組可以使用C#很容易地操縱的對象。為了更好地構(gòu)成我的解決方案, 我已經(jīng)決定把所有的通信相關(guān)類與REST API (如服務(wù)和實(shí)體)放置在另一個(gè)叫做InfoSeries.Core的便攜式類庫(Portable Class Library)中,這是一個(gè)與實(shí)際Xamarin Forms應(yīng)用程序的相比不同的PCL。

這就是負(fù)責(zé)解析之前的JSON的方法返回一個(gè)C#對象列表:

public async Task<List<SerieFollowersVM>> GetStatsTopSeries()
{
    using (HttpClient client = new HttpClient())
    {
        try
        {
            var response = await client.GetAsync("//api.trackseries.tv/v1/Stats/TopSeries");
            if (!response.IsSuccessStatusCode)
            {
                var error = await response.Content.ReadAsAsync<TrackSeriesApiError>();
                var message = error != null ? error.Message : "";
                throw new TrackSeriesApiException(message, response.StatusCode);
            }
            return await response.Content.ReadAsAsync<List<SerieFollowersVM>>();
        }
        catch (HttpRequestException ex)
        {
            throw new TrackSeriesApiException("", false, ex);
        }
        catch (UnsupportedMediaTypeException ex)
        {
            throw new TrackSeriesApiException("", false, ex);
        }
    }
}

HttpClient類的GetAsync() 方法執(zhí)行GET請求到URL,返回結(jié)果包含JSON響應(yīng)的字符串。這個(gè)結(jié)果存儲(chǔ)在響應(yīng)的Content 屬性:如果請求成功(我們使用IsSuccessStatusCode 屬性檢查這種情況),我們使用Content 屬性公開的ReadAsAsync< T >方法自動(dòng)轉(zhuǎn)換為JSON導(dǎo)致SerieFollowersVM 對象的集合。SerieFollowersVM 無非是一個(gè)映射JSON響應(yīng)的每個(gè)屬性的類 (如name、countryruntime)到一個(gè)C#屬性:

public class SerieFollowersVM
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Followers { get; set; }
    public DateTimeOffset FirstAired { get; set; }
    public string Country { get; set; }
    public string Overview { get; set; }
    public int Runtime { get; set; }
    public string Status { get; set; }
    public string Network { get; set; }
    public DayOfWeek? AirDay { get; set; }
    public string AirTime { get; set; }
    public string ContentRating { get; set; }
    public string ImdbId { get; set; }
    public int TvdbId { get; set; }
    public string Language { get; set; }
    public ImagesSerieVM Images { get; set; }
    public ICollection<GenreVM> Genres { get; set; }
    public DateTime Added { get; set; }
    public DateTime LastUpdated { get; set; }
    public string SlugName { get; set; }
}

在GitHub的完整示例(為了方便各位讀者,小編已經(jīng)為大家整理了,請點(diǎn)擊這里下載)中你會(huì)發(fā)現(xiàn)很多這樣的類(映射各種被TrackSeries API返回的JSON響應(yīng))。此外,TsApiService 將實(shí)現(xiàn)另外的方法,一個(gè)用于我們想在我們的應(yīng)用程序中利用的每個(gè)API的方法。我不會(huì)詳細(xì)解釋每個(gè)方法,因?yàn)檫@將超出本文的范圍,你可以在GitHub上看到所有的細(xì)節(jié)。對于這篇文章的目的,你只需要知道服務(wù)只是公開了一組方法,我們可以在各種ViewModels中使用來檢索可用的電視節(jié)目的信息。

注意:默認(rèn)情況下,HttpClient 類沒有提供一個(gè)ReadAsAsync< T >方法,能夠自動(dòng)對JSON響應(yīng)為C#對象進(jìn)行反序列化。為了獲得該擴(kuò)展方法,我們需要添加Microsoft.AspNet.WebApi.Client NuGet包到便攜類庫(Portable Class Library)。為了讓它正常工作,你需要將這個(gè)包添加到解決方案的每個(gè)項(xiàng)目(Xamarin Forms PCL、Core PCL和所有特定于平臺(tái)的項(xiàng)目)。

然而,為了正確利用依賴注入(dependency injection),我們需要一個(gè)接口來描述TsApiService 類提供的操作。這就是我們的接口的樣子:

public interface ITsApiService
{
    Task<List<SerieFollowersVM>> GetStatsTopSeries();
    Task<SerieVM> GetSerieByIdAll(int id);
    Task<SerieInfoVM> GetSerieById(int id);
    Task<List<SerieSearch>> GetSeriesSearch(string name);
    Task<SerieFollowersVM> GetStatsSerieHighlighted();
}

現(xiàn)在我們有了一個(gè)服務(wù),我們可以學(xué)習(xí)(多虧Prism)我們可以如何注冊到它的依賴容器,它會(huì)自動(dòng)注入在我們的ViewModels。實(shí)際上,從這個(gè)角度來看,沒有什么特別強(qiáng)調(diào):這與其他MVVM框架使用的方法是相同的,利用依賴注入的方法。首先,我們需要注冊我們想要在容器中使用的接口和實(shí)現(xiàn)之間的協(xié)會(huì)。在Prism的情況下,我們需要用App類的RegisterTypes()方法,通過使用Container對象和RegisterType< T, Y >()方法(其中T 是接口,Y是具體實(shí)現(xiàn)):

protected override void RegisterTypes()
{
    Container.RegisterTypeForNavigation<MainPage>();
    Container.RegisterType<ITsApiService, TsApiService>();
}

當(dāng)MainPage TsApiService 都在容器注冊了,我們可以在ViewModel獲得它,只需添加一個(gè)參數(shù)在公共構(gòu)造函數(shù),就像以下示例:

public class MainPageViewModel : BindableBase
{
    private readonly ITsApiService _apiService;
    public MainPageViewModel(ITsApiService apiService)
    {
        _apiService = apiService;
    }
}

MainPageViewModel 類將被加載時(shí),我們已經(jīng)在容器注冊的ITsApiService實(shí)現(xiàn)(在我們的例子中是TsApiService 類)將自動(dòng)注入構(gòu)造函數(shù)的參數(shù),允許我們以我們將在ViewModel創(chuàng)建的所有其他的方法和屬性來使用它。使用這種方法,我們將容易改變服務(wù)的實(shí)現(xiàn),以防我們需要它:它將足以改變App類的注冊類型,并且每個(gè)ViewModel將自動(dòng)開始使用新的版本。

處理導(dǎo)航的生命周期

現(xiàn)在我們有一個(gè)服務(wù),它提供了一種方法來檢索頂級系列的列表,在ViewModel加載時(shí)我們需要調(diào)用它。我們的目標(biāo)是顯示(在應(yīng)用程序的主頁)最熱門的電視節(jié)目列表。但是,我們即將面對使用MVVM模式時(shí)的一個(gè)常見的問題:檢索頂級系列列表的方法是異步的,但是隨著當(dāng)前實(shí)現(xiàn),唯一我們可以執(zhí)行數(shù)據(jù)加載的地方就是ViewModel的構(gòu)造函數(shù),它不能執(zhí)行異步調(diào)用(在C#中,事實(shí)上,一個(gè)類的構(gòu)造函數(shù)不能用async關(guān)鍵字,因此,你不能用等待前綴的方法)。在non-MVVM應(yīng)用程序中,這個(gè)問題很容易解決,因?yàn)閷?dǎo)航的生命周期方法是由每一個(gè)平臺(tái)基本提供的。Xamarin Forms毫無例外,我們可以利用(在XAML頁面類的后面的代碼)OnAppearing()OnDisappearing()方法:因?yàn)樗鼈兪鞘录?,我們可以沒有問題地調(diào)用異步代碼。

為了解決這個(gè)問題,Prism提供一個(gè)稱為INavigationAware的接口,我們可以在ViewModels實(shí)現(xiàn)。當(dāng)我們實(shí)現(xiàn)它,我們可以訪問OnNavigatedTo()OnNavigatedFrom()事件,我們可以使用它們來執(zhí)行數(shù)據(jù)加載或清理操作。這就是實(shí)現(xiàn)這個(gè)接口后我們的MainPageViewModel 的樣子:

public class MainPageViewModel : BindableBase, INavigationAware
{
    private readonly TsApiService _apiService;
    private ObservableCollection<SerieFollowersVM> _topSeries;
    public ObservableCollection<SerieFollowersVM> TopSeries
    {
        get { return _topSeries; }
        set { SetProperty(ref _topSeries, value); }
    }
    public MainPageViewModel(TsApiService apiService)
    {
        _apiService = apiService;
    }
    public void OnNavigatedFrom(NavigationParameters parameters)
    {
    }
    public async void OnNavigatedTo(NavigationParameters parameters)
    {
        var result = await _apiService.GetStatsTopSeries();
        TopSeries = new ObservableCollection<SerieFollowersVM>(result);
    }
}

正如你所看到的,現(xiàn)在我們實(shí)現(xiàn)了一個(gè)稱為OnNavigatedTo()的方法,我們可以安全地執(zhí)行異步調(diào)用和加載數(shù)據(jù)。我們調(diào)用TsApiService類的GetStatsTopSeries()方法,我們封裝結(jié)果集合到ObservableCollection屬性。這是我們要連接的屬性,通過綁定到一個(gè)ListView 控件,為了在主頁顯示電視節(jié)目列表。

出于完整性的考慮,這是MainPage的XAML的樣子:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="//xamarin.com/schemas/2014/forms"
             xmlns:x="//schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="InfoSeries.Views.MainPage"
             Title="Info Series">
  <ContentPage.Resources>
    <ResourceDictionary>
      <DataTemplate x:Key="TopSeriesTemplate">
        <ViewCell>
          <ViewCell.View>
            <Grid>
              <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*" />
                <ColumnDefinition Width="2*" />
              </Grid.ColumnDefinitions>
              <Image Source="{Binding Images.Poster}" Grid.Column="0" x:Name="TopImage" />
              <StackLayout Grid.Column="1" Margin="12, 0, 0, 0" VerticalOptions="Start">
                <Label Text="{Binding Name}" FontSize="18" TextColor="#58666e" FontAttributes="Bold" />
                <StackLayout Orientation="Horizontal">
                  <Label Text="Runtime: " FontSize="14" TextColor="#58666e" />
                  <Label Text="{Binding Runtime}" FontSize="14" TextColor="#98a6ad" Margin="5, 0, 0, 0" />
                </StackLayout>
                <StackLayout Orientation="Horizontal">
                  <Label Text="Air day: " FontSize="14" TextColor="#58666e" />
                  <Label Text="{Binding AirDay}" FontSize="14" TextColor="#98a6ad" Margin="5, 0, 0, 0" />
                </StackLayout>
                <StackLayout Orientation="Horizontal">
                  <Label Text="Country: " FontSize="14" TextColor="#58666e" />
                  <Label Text="{Binding Country}" FontSize="14" TextColor="#98a6ad" Margin="5, 0, 0, 0" />
                </StackLayout>
                <StackLayout Orientation="Horizontal">
                  <Label Text="Network: " FontSize="14" TextColor="#58666e" />
                  <Label Text="{Binding Network}" FontSize="14" TextColor="#98a6ad" Margin="5, 0, 0, 0" />
                </StackLayout>
              </StackLayout>
            </Grid>
          </ViewCell.View>
        </ViewCell>
      </DataTemplate>
    </ResourceDictionary>
  </ContentPage.Resources>
  <ListView ItemTemplate="{StaticResource TopSeriesTemplate}"
            ItemsSource="{Binding Path=TopSeries}" RowHeight="200"/>
</ContentPage>

如果你已經(jīng)知道Xamarin Forms(或一般的XAML),你應(yīng)該會(huì)覺得這段代碼很容易理解:頁面包含一個(gè)ListView 控件、一個(gè)描述單個(gè)電視節(jié)目的模板。我們展示節(jié)目的海報(bào),還有一些其他信息,如標(biāo)題、運(yùn)行時(shí)、生產(chǎn)國家等等。因?yàn)椋ǜ鶕?jù)命名約定)MainPageViewModel 類已經(jīng)設(shè)置為頁面的BindingContext ,我們可以通過綁定ListViewItemsSource屬性和我們之前在ViewModel填充的TopSeries集合進(jìn)行簡單地連接。

導(dǎo)航與參數(shù)

我們已經(jīng)看到了如何利用OnNavigatedTo()方法來執(zhí)行數(shù)據(jù)加載,但通常這種方法在另一個(gè)場景中也是有用的:檢索參數(shù)通過前一頁,這通常需要了解當(dāng)前的上下文(在我們的示例中,在我們的應(yīng)用程序的詳細(xì)信息頁面,我們需要理解用戶已經(jīng)選擇的電視節(jié)目)。

Prism支持這個(gè)特性是由于一個(gè)稱為NavigationParameters的類稱,可以作為NavigationServiceNavigationAsync()方法的一個(gè)可選參數(shù)傳遞,它被自動(dòng)包括作為OnNavigatedTo()OnNavigatedFrom()事件的參數(shù)。讓我們看看如何通過向我們的應(yīng)用程序添加詳細(xì)信息頁面利用這個(gè)特性,顯示選擇的節(jié)目的一些額外的信息。

第一步是同時(shí)添加一個(gè)新頁面到Views 文件夾中(稱為DetailPage.xaml)和一個(gè)新類到ViewModels文件夾中(稱為DetailPageViewModel.cs)。你需要記住,每一頁都需要在App類的容器中注冊,在OnRegisterTypes()方法內(nèi):

protected override void RegisterTypes()
{
    Container.RegisterTypeForNavigation<MainPage>();
    Container.RegisterTypeForNavigation<DetailPage>();
    Container.RegisterType<ITsApiService, TsApiService>();
}

由于命名約定,我們不需要做任何特別的操作:新頁面和新ViewModel已經(jīng)連接?,F(xiàn)在我們需要通過ListView控件中所選條目到新頁面。讓我們先看看如何在主頁處理選擇。通過使用由我親愛的朋友Corrado Cavalli創(chuàng)建的庫,我們會(huì)得到一些幫助,它允許你在Xamarin Forms應(yīng)用程序?qū)崿F(xiàn)行為??捎玫男袨橹械?strong>EventToCommand允許我們連接暴露于控件的任何事件與ViewModel中定義的命令。我們要用它來連接ListView 控件的ItemTapped 事件(當(dāng)用戶點(diǎn)擊列表中的一個(gè)項(xiàng)目時(shí)會(huì)觸發(fā))與我們要在MainPageViewModel中創(chuàng)建來觸發(fā)導(dǎo)航到詳細(xì)頁面的命令。

你可以從NuGet安裝由Corrado創(chuàng)建的套包,它的名字叫Corcav.Behaviors。使用它你需要添加一個(gè)額外的名稱空間到MainPage的root,像下面這個(gè)示例:

<ContentPage xmlns="//xamarin.com/schemas/2014/forms"
             xmlns:x="//schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             xmlns:behaviors="clr-namespace:Corcav.Behaviors;assembly=Corcav.Behaviors"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="InfoSeries.Views.MainPage"
             Title="Info Series">
    ...
</ContentPage>

然后你可以申請ListView 控件的行為,就像你在普通Windows應(yīng)用程序中會(huì)做的一樣:

<ListView ItemTemplate="{StaticResource TopSeriesTemplate}"
          ItemsSource="{Binding Path=TopSeries}" RowHeight="200">
  <behaviors:Interaction.Behaviors>
    <behaviors:BehaviorCollection>
      <behaviors:EventToCommand EventName="ItemTapped" Command="{Binding GoToDetailPage}" />
    </behaviors:BehaviorCollection>
  </behaviors:Interaction.Behaviors>
</ListView>

由于這種行為,我們已經(jīng)連接了ListView 控件的ItemTapped 事件與我們要在ViewModel定義的稱為GoToDetailPage 的命令。從一個(gè)框架的角度,Prism沒有做任何不尋常的事幫助開發(fā)者實(shí)現(xiàn)命令:它只是提供了一個(gè)稱為DelegateCommand的類,這允許你定義操作來執(zhí)行調(diào)用命令和可選的條件來啟動(dòng)命令。如果你有一些MVVM Light以往的經(jīng)驗(yàn),它會(huì)以RelayCommand 類那樣完全相同的方式運(yùn)作。以下是我們的命令在MainPageViewModel 類的樣子:

private DelegateCommand<ItemTappedEventArgs> _goToDetailPage;
public DelegateCommand<ItemTappedEventArgs> GoToDetailPage
{
    get
    {
        if (_goToDetailPage == null)
        {
            _goToDetailPage = new DelegateCommand<ItemTappedEventArgs>(async selected =>
            {
                NavigationParameters param = new NavigationParameters();
                param.Add("show", selected.Item);
                await _navigationService.NavigateAsync("DetailPage", param);
            });
        }
        return _goToDetailPage;
    }
}

我們已經(jīng)創(chuàng)建了的命令是一個(gè)參數(shù)化命令;事實(shí)上,屬性類型是DelegateCommand< ItemTappedEventArgs >:這種方式,在方法內(nèi)部,我們獲得存儲(chǔ)在Item 屬性中的選中的條目。命令觸發(fā)時(shí)調(diào)用的方法展示了如何用參數(shù)的工作原理導(dǎo)航:首先我們創(chuàng)建一個(gè)新的NavigationParameters對象,最后,只不過是一個(gè)你可以存儲(chǔ)鍵/值對的字典。因此,我們只需添加一個(gè)新項(xiàng),作為關(guān)鍵,關(guān)鍵字show ,作為值,選中的項(xiàng)的類型是SerieFollowersVM。這是與我們在App類中看到的導(dǎo)航的唯一的區(qū)別:其余的都是一樣的,這意味著我們調(diào)用NavigationServicetheNavigateAsync()方法,傳遞標(biāo)識(shí)詳細(xì)信息頁面(DetailPage)和參數(shù)的關(guān)鍵參數(shù)。

重要事項(xiàng)!App類中,我們能夠自動(dòng)使用NavigationService ,因?yàn)樗^承自PrismApplication 類。如果我們要在ViewModel中使用NavigationService (像在這種情況下),我們需要使用基于依賴注入(dependency injection)的傳統(tǒng)方法。NavigationService 實(shí)例已經(jīng)在Prism容器注冊,所以我們只需要添加一個(gè)INavigationService 參數(shù)到MainPageViewModel的公共構(gòu)造函數(shù):

public MainPageViewModel(TsApiService apiService, INavigationService navigationService)
{
    _apiService = apiService;
    _navigationService = navigationService;
}

既然我們已經(jīng)完成了導(dǎo)航到詳細(xì)頁面,我們就需要檢索DetailPageViewModel 類的參數(shù)。第一步,像我們?yōu)?strong>MainPageViewModel做的那樣,讓它從INavigationAware 接口繼承,除了BindableBase 類。通過這種方式,我們可以訪問OnNavigatedTo()事件:

public class DetailPageViewModel : BindableBase, INavigationAware
{
    private SerieFollowersVM _selectedShow;
    public SerieFollowersVM SelectedShow
    {
        get { return _selectedShow; }
        set { SetProperty(ref _selectedShow, value); }
    }
    public DetailPageViewModel()
    {
    }
    public void OnNavigatedFrom(NavigationParameters parameters)
    {
    }
    public void OnNavigatedTo(NavigationParameters parameters)
    {
        SelectedShow = parameters["show"] as SerieFollowersVM;
    }
}

前面的代碼顯示了如何處理我們從主頁收到的參數(shù):同一個(gè)我們通過的MainPageViewModel對象到作為 OnNavigatedTo()方法的參數(shù)傳遞的NavigateAsync()方法。因此,我們可以用show 鍵簡單的檢索先前存儲(chǔ)的項(xiàng)。在這種情況下,因?yàn)槲覀冾A(yù)計(jì)SerieFollowersVM類型的對象,我們可以執(zhí)行一個(gè)計(jì)算并將其存儲(chǔ)到稱為SelectedShow的ViewModel的屬性中。多虧了這個(gè)屬性,我們可以利用綁定到選擇顯示的各種信息連接到XAML頁面的空間。以下是DetailPage.xaml的樣子:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="//xamarin.com/schemas/2014/forms"
             xmlns:x="//schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             Title="{Binding Path=SelectedShow.Name}"
             x:Class="InfoSeries.Views.DetailPage">
  <StackLayout>
    <Image x:Name="InfoPoster"
           Source="{Binding Path=SelectedShow.Images.Fanart}" Aspect="AspectFill" />
    <Label Text="{Binding Path=SelectedShow.Overview}" LineBreakMode="WordWrap" FontSize="13" TextColor="#98a6ad" Margin="15" />
  </StackLayout>
</ContentPage>

內(nèi)容很簡單:我們顯示show的圖片(存儲(chǔ)在SelectedShow.Images.Fanart屬性)和一段簡要描述(存儲(chǔ)在SelectedShow.Overview屬性)。

結(jié)束語

在這篇文章中,我們已經(jīng)看到在用Prism 作為MVVM框架創(chuàng)建的Xamarin Forms應(yīng)用程序中處理導(dǎo)航和依賴注入的一些基本概念。在下一篇文章中,我們將看到幾個(gè)高級場景,有關(guān)導(dǎo)航和特定于平臺(tái)的代碼的處理。你能在GitHub存儲(chǔ)庫找到這篇文章使用的示例應(yīng)用程序(為了方便各位讀者,小編已經(jīng)為大家整理了,請點(diǎn)擊這里下載)。

本文翻譯自:

 

PS: 關(guān)于移動(dòng)開發(fā),這些產(chǎn)品你可以關(guān)注>>
關(guān)于移動(dòng)開發(fā)的最新資訊和產(chǎn)品推薦,請<>!
掃碼咨詢


添加微信 立即咨詢

電話咨詢

客服熱線
023-68661681

TOP
国产一区二区三区不卡在线看 | 91九色国产| 国产剧情av在线观看 | 亚洲av无码久久久久久精品同性 | 国产精品免费久久久久影院 | 亚洲综合无码精品一区二区三区 | 国产精品丝袜久久久久久不卡 | av毛片 | 精品人妻无码一区二区三 | 成人在线免费观看 | 欧美丝袜高跟鞋一区二区 | 亚洲一区二区天海 | 国产福利一区二区三区在线 | 欧美大片va欧美在线播放 | 日韩精品一区二区最新 | 日韩好片一区二区在线看 | 99久久精品国产 | 精品国产91乱码一区二区三区 | 国产av无码专区亚洲精品 | 人人揉人人爽五月天视频 | 欧美亚洲国产日韩一二三区 | 日韩精品精品一区二区三区 | 日韩av午夜无码专区 | 亚洲精品少妇久久久久久希岛爱理 | 99久久免费看片 | 91精品国产麻豆国产自产 | 最新国产精品鲁鲁免费视频 | 国产欧美| 在线一本到无码av | 伊人色综合网一区二区三区 | 亚洲国产区视频在线观看免费视 | 成人毛片无码一区二区三区 | 日韩精品一区二区三区四区免费 | 日韩av免费观看中文字幕 | 亚洲精品乱码97久久久久久丝袜 | 一区二区三区国 | 蝌蚪窝在线观看免费视频 | 午夜福制92视频 | 超碰97人人做人人爱网站 | 欧美一级夜爽爽爽在线播放 | 国产99一区免费视 | 国产h视频在线观看 | 国产亚洲精品a等一页 | 欧美综合 | 99精品国产在热久久无码 | 亚洲午夜无码久久久久软件 | 亚洲av专区无码观看精品天堂 | 亚洲精品视频 | 99精品一区二区三区无码吞精 | 精品国产主播在 | 国内精品久久久久久久久久影视 | 91人人 | 91精品视频在线看 | 麻豆精产国品免费免 | 国产主播大尺度精品福利 | 国产成人av无码片在线影院 | 国产高清极品美女黄色网站 | 欧美日韩在线一区乱码视频 | 国产一视频在线观看 | 波多野たの结衣在线播放 | 黄色视频日本wwwww | 婷婷久久青草99热福利 | 亚洲欧美高清精品ⅴ | 天天干天天操天天 | 中文字幕aav | 蝌蚪窝在线观看免费视频 | 91在线看片 | 少妇裸体春药高潮精油按摩 | 黄色视频在线免费观看 | 国产精品亚洲一区二区在线观看 | 波多野结衣视频在线观看 | 婷婷中文视频在线 | 日本深夜福利19禁在线播放 | 91久久偷偷做嫩草影院免费看 | 国产91最新欧美在线 | 日韩在线视频播放 | 欧美一级二级一区二区 | 日本免费人成视频在线观看 | 欧美又粗又大bbbb疯视频av | 日韩不卡毛片av免费高清 | 亚洲v国产v天堂网 | 蜜臀av一区二区三区久久 | 牛牛精品国产亚洲一区二区三区 | 亚洲国产精品无码一区二区 | 国产亚洲成av人片在线观看 | 午夜亚洲国产理论片4080 | 午夜精品久久 | 国产乱理伦片在线观看 | 日本老司机午夜福利在线免费观看 | 午夜福利一区二区三区不卡 | 99久久婷| 日韩久久精品无码av | 欧美一区二区三区视频在线 | 国产一区二区三区不卡在线观看 | 专区在线播放中文 | 中文字幕乱人伦视频在线 | 亚洲午夜久久久影院伊人 | 欧美日韩在线一区二区 | 97人妻精品一区二区三区免 | 91大神在线观看 | 91精品国产麻豆91久久久久久 | 亚洲欧美日韩、中文字幕不卡 | 中文字幕精品无码亚洲幕 | 国产免费永久视频观看 | a级伦国产乱理片在线观看 a级毛片 | 国产av亚洲精| 亚洲aⅴ男人的天堂在线观看 | 成人aaa片一区国 | 亚洲国产日韩a在线播放 | 加勒比在线一区二区三区 | 中日韩精品无码一区二区三区 | 怡红院aⅴ国产一 | 精品国产福利在线观看 | 成人永久免费黄色在线观看网站 | 日韩精品亚洲人成在线观看亚洲 | 欧美亚洲综合色 | 午夜剧场成人免费久久精品 | 少妇有精又色又爽的视频 | 国产在线一区二区三区av | 亚洲伊人精品国产欧美目韩 | 亚洲精品无码久久久 | 日韩一区二区三区 | 91天堂国产在线 | 精品蜜臀久久久久99网站 | 欧美一级手| 成人亚洲性情网站www在线观看 | 狠狠躁夜夜躁人人爽天天开心 | 精品熟女国产久久少妇aⅴ免费狠 | 风流老熟女一区二区三区l 风流老太婆大bbw | 午夜视频在线会员国产 | 天天爽夜夜春 | 91亚洲精品国产自在现线 | 午夜桃色 | 成年人黄页 | 亚洲精品无码久久久影院相关影片 | 国产国语三级黄色战线免费观看av | 中文字幕亚洲情99在线 | 天天人人综合网7799 | 中文字幕人成乱 | a级大片免费观看 | 国产原创91 | 天天干天天操天天摸 | 日本多人强伦姧人妻完整版 | 国产av午夜精品一区二区入口 | 欧美午夜一区二区福利视频 | 毛片久久久久久久久 | 国产精品视频专区 | 99国产在线视频 | 久久99国产精品二区 | 亚洲av永久无码精品网站 | 成人亚洲欧美久久久久 | 女人三级片电影一区二区区 | 午夜av无码福利免 | 欧美成人精品第一区二区三区 | 欧美精品第欧美第12页 | 在线播放午夜理论片 | 亚洲无码人成在线 | 国产精品无码一区二 | 欧美日韩无线码在线观 | 99精品国产在热久久国产乱 | 在线视频中文 | 无码不卡av东京热毛片 | 日本视频免费观看的网站 | 国产精品美女自在线观看免费 | 亚洲熟妇无码av在线观看 | 国产成人久久精品激情 | 国产成人亚洲综合无码ⅴ | 国产精品成人一区二区不卡 | 国产ts在线 | 欧美大片va| 办公室大战高跟丝袜秘书经理ol | 国产精品高清一区二区三区 | 97人妻免费在线视频中文 | 在线视频你懂的中文字幕 | 亚洲熟女乱色一区二区三区 | 无码国产成人久久 | 国内一级 | а√天堂网www在线 а√天堂网www在线搜索 | 狠狠色综合久久丁香婷婷 | 日韩丰满少妇无码内射 | 亚洲综合无码中文字幕 | 国产精品自产拍在线网站 | 日本欧美中文字幕人在线 | 午夜精品无码免费视频 | 国产香蕉视频免费精品 | 精品三级乱伦免费 | 国产精品美女乱子伦高潮 | 欧日片布费看美 | 无码在线一区二区在线观看网站 | 狠狠色丁香婷婷综合尤物 | 麻豆一区二区99久久久久 | 亚洲成av人片在一线观看 | 国产一区二区三区不卡av | 欧美一区二区三区性视频 | 麻豆视频网站男人的天堂 | 91九色porny永久地址 | 亚洲成a∨人片在无码 | 国产亚洲色婷婷久久99精品91 | 国产高潮国产高潮久久久91 | 超国产人碰人摸人爱视频 | 69国产成人综合久久精 | 色狠狠色狠狠综合天天 | 在线免费观看小视频 | 欧美视频一区二区三区在线观 | 午夜福利理论片在线观看 | 亚洲熟妇无码另类久久久 | 在线观看黄色小视频 | 亚洲无码宅男在线 | 国产视频一区二区 | 丝袜中出制服人妻美腿 | 久久不见久久见免费影院www日本 | 精品三级久久久久久久 | 国产女主播喷水视频在线观看 | 成人免费aaaaa毛片 | 综合色五月久久激情婷 | 国产av无码专区亚洲av | 91久久大香伊蕉在人线 | 日韩精品久久久毛片一区二区 | 国产精品岛国久久久久久 | 无码不卡在线观看 | 国产成人亚洲精品无码青app | 爆乳无码一区二区在线观看ai | 婷婷婷国产在线视频 | 欧美午夜精品一区二区蜜桃 | 日韩美一区二区 | 中文字幕一区二区三区 | 在线观看一区二区三区av | 97青草操五月天开心网 | 亚洲欧美人成网站综合在线 | 国产产区一| 无码国产精品一区二区高潮 | av网站在| 欧洲无码 | 精品久久久久久无码中文字幕 | 亚洲视频精品视频 | 日韩一区二区中文字幕 | 亚洲欧美日韩、中文字幕不卡 | 国产成人精品国产成人亚洲 | 国产精品精品综合在线网 | 日韩爽爽视频爽爽 | 国产午夜理论片不卡在线观看 | 亚洲精品欧美精品日韩精品 | 国产suv视频大全 | 国产v欧美v亚洲v日本久久 | 韩国r级无码电影在线观看 韩国r级无码片在 | 亚洲国产av无码精品 | 香蕉天天综合网日韩欧影视 | 91成人免费视频 | 日本欧美一区二区三区乱码 | 中文亚洲av片在线观看无码 | 亚洲国产一区二区在线观看 | 韩国无码av片在线观看网站 | 神马午夜av午夜一二区 | 黄片视频 | 日韩亚洲欧美久久久www综合网 | 成年人免费视频在 | 国产精品99久久久久人中文网介绍 | 久久r视频免精品在 | 91麻豆精产国品一二三系列产品测评 | 国产高清一区二区三区人妖 | 香蕉视频直播免费直播app正式版 | 日韩欧美自在线观看亚洲精品福利片 | 1区2区3区视频软件排行榜 | 动漫精品一区二区三区 | 99re这里精品视频7 | 免费无遮挡又黄又爽网站 | 99久久精品无码专区 | 中文字幕一区波多野结衣 | 欧美一级黄色片免费看 | 无码专区一va亚洲v专区在线 | 国产一区二区视频 | 中文字幕在线资源站 | 无码人妻精品中文字幕免费东京热 | 91精品天美精东蜜桃传媒入口 | 香蕉久久国产av一区二区 | 国产一区二区三区免费看 | 97se亚洲综合自在线 | 欧美午夜精品 | 日韩亚洲欧美久久久www综合网 | 国产精品久久久久精品综合 | 91视频专区 | 91麻豆精品国产91久久久久久 | 国产一级二级在线观看 | 在线观看午夜亚洲一区 | 欧美精品视频一区二区三区 | 久草免费版官方最新版下载 | 精品视频在线播放一区二区三区 | 四虎影视久久久免费 | 国产区视频在线观看 | 成人免费a级毛片 | 国产a一级无码毛片一区二区三区 | 成年人网站在线免费观看 | 99精品国产综合久久五月天 | 精品91自产拍 | 亚洲国产第 | 国产不卡高清视频在线观看 | 人妻久久精品天天中文字幕 | 人人爽人妻精品a片二区 | 亚洲视频在线网 | 国产三级在线 | 国产在线一区二 | 亚洲午夜精品久久久久久app | 午夜成人理论无码电影在线播 | 91在线播放视频 | 人妻插b视频一区二区三区 人妻潮喷失禁dh | 亚洲欧美日韩久久 | 四虎国产精品成人免费久久 | 超级碰97直线国产免费公开 | 色一情一区| 国产97视频| 日韩精品一区二区三区高清免费 | 亚洲av无码成h人动漫在线观看 | 国产婷婷综合在线视频 | 亚洲尺码一区二区三区 | 99东京热这里有精品 | 无码人妻免费—区二区三 | 亚洲av永久无码天堂网国产 | 亚洲av久久无码精品九九 | 婷婷色爱区综合五月激情 | 91精品啪在线观看国产线免费 | 黄a大片av永久免费 黄瓜视频在线观看 | 欧美精品一区二区三区在线观看 | 99久久精品熟女高潮喷水免费 | 福利影视| 日韩成人男女福利电影在线播放网站 | 99久久精品熟女高潮喷水免费 | 精品國產福利第一區二區三區 | 天天干天天操夜夜嗨 | 少妇高潮毛片色欲ava片 | 精品久久无码中文字幕一区 | 亚洲av成人无码一二三在线观看 | 久久er99国产精品免费 | 亚洲中文字幕码在线电影 | 久久国产91成人免费网站 | 中文字幕熟妇人妻在线视频 | 91在线视精品在亚洲 | 精品国产亚洲一区二区三区 | 日本高清中文字幕在线 | 天天免费在线看片 | 亚洲av无码av专区在线观看 | 九一成人在 | 国产精品视频一区 | 亚洲一卡一卡二 | 国产一级a在线观看 | 久久99久久精品久久久久久 | 国内盗摄视频一区二区三区 | 国产精品高清视亚洲 | 91信用卡app下载安装 | 亚洲精品无码不卡 | 国产99一区免费视 | 欧洲一级一片在线观看免费精品色 | 动漫3d精品一区二区三区乱码 | 欧美成人精品一区二区三区 | 亚洲线精品一区二区三区 | 中文字幕亚洲男人的天堂网络 | 国产亚洲精品成 | 午夜精品久久久久久久99热蜜桃 | 精品亚洲国产专区在线观看 | 亚洲综合国产一区二区三区 | 白丝袜白高跟鞋 | 99精品国产一区二区三区四区阿崩 | 国产九九在线 | 精品福利视频导航 | 波多野结衣av无码 | 国产av一区二区三区最新精品 | 午夜精品久久久久久久无码 | 欧美午夜不卡在线观看 | 国产精品偷伦视频免费观看 | 91香蕉国产在线观看免费永久 | 亚洲精品一区二区在线 | 国产成人精品视频一区二区不卡 | 色综合久 | 国产午夜精品一区二区三区不卡 | 亚洲精品老司机在线观看 | 狠狠色狠狠综合天天 | 中文字幕亚洲综合久久青草 | 免费一级全黄少妇性色生活 | 精品人妻人人做人人爽夜夜爽 | 91九色porny永久地址 | 伊人中文字| 国产无套粉嫩白浆在线观看 | 国产成人啪精品视频免费网 | 国产午夜精品一区二区三区四区 | 十大最污日本动漫都是少儿不宜啊! | 中日韩一区二区三区 | 东京热一区二区三区无码视频 | 丰满人妻熟妇乱又伦精品软件 | 超碰久久人人摸人人搞 | 国产视频一区二区在线观看 | 国产91精品丝袜一区二区 | 欧美高清在线观看海外剧在线观看 | av午夜午夜快憣免费软件 | 精品国产国语 | 成人综合高清久久亚洲中文字幕精 | 精品久久久无码人妻字幂 | 成人免费a级毛片 | 国产人妇三级视频在线观看 | 日韩三级在线观看 | 人人揉揉香蕉 | 欧美孕妇变态重口另类 | 91影院| 精品国产福利第 | 欧美剧情视频在线播放 | 无码人妻一区二区三区精品视频 | 国产综合久久久久久 | av一本久道久久综合久久鬼色 | 国产日韩亚洲欧美精品专区 | 99久久亚洲国产高清观看 | 国产精品青草久久久久福利99 | 成人高清图片下载 | 精品国产一区二区三区久久影院 | 无码av一区在线观看免费 | 国产欧美日韩视频在线观看 | 91国在线啪精品一区 | 国产一区二区三区无码免费 | 日韩十八禁在线1区2区3区不卡 | 欧美日韩在线精品一区二区 | 91av在线免费观看 | 亚洲国产成人久久一区 | 亚洲国产精品国自产拍av | 亚洲午夜无码片在线观看影院百度 | 亚洲欧美人成电影在线观看 | 97碰碰碰| 精品久久久久久久中文字幕 | 不卡一区二区在线观看 | 欧美亚洲成人动漫在线 | 国产免费aⅴ大片在线 | 午夜视频福利 | 国产在线一区二区三区欧美 | 国产热无码手机 | 亚洲一区亚洲二区 | 久久av老司机精品网站导航 | 久本草在线中文字幕 | 国产精品99无码一区二蜜桃 | 亚洲一级在线观看 | 亚洲成在人线aⅴ中文字幕 亚洲成在人线av壁咚影院 | 91在线免 | 超薄丝袜足j好爽在线 | 亚洲欧美福利一区二区 | 国产亚洲一级毛片 | 成年人在线播放视频 | 国产成人高清亚洲第一 | 国产一级做a爰片久久毛片男 | 日韩成人一区二区三区在线观看 | 91香蕉成人app最新版官网 | 国产精品亚洲一区二区三区在线 | 国产真人无码作爱免费视频 | 亚洲男人的天堂在线播放 | 国产v日本v欧美v一二三四区 | 国产精品无码一区二区三区在 | 国产私密网站入口 | 成年肉动漫在线观看无修 | 91麻豆免费 | 中文字幕日韩人妻无码 | 国产成人亚洲影院在线观看 | 尤物久久精品极品 | 丰满人妻一区三区 | 亚洲欧美手机在线观看 | 91精产品一永久下载安装免费 | 午夜一区二区免费福利麻豆 | 色婷婷在| av一区二区三区不卡在线 | 另类小说 | 无码日韩精品一区二区免费 | 丰满爆乳肉感一区二区三区 | 免费无码在线观看久久精品视频国产 | 亚洲精品国产午夜福 | 日日干夜夜爽 | 日韩精品一区二区三区视频 | 91精品无人区麻豆 | 岛国一区二区在线观看蜜 | 97人妻人人做人碰人人爽 | 国产精品丝袜一区二区三区 | 在线观看麻豆 | 国产精品亚洲a∨天堂不卡 国产精品亚洲av高清二区 | 91po最新| 亚洲精品国产男 | 午夜精品无人区乱码1区2区 | 国产色青青视频在线观看撒 | 国产日韩精品无码区免费专区国产 | 亚洲日韩av无码一区二区三区 | 日本japa| 91视频最新网址 | 少妇被躁爽到高潮无码文 | 国产亚洲精品91 | 亚洲精品午夜 | 国产露脸对白91精品 | 日本成人网在线观看 | 毛片在线播放网 | 国产成人精品无码免费播放 | 亚洲av无码专区在线亚 | 亚洲精品aa片在线观看国产 | 丝袜灬啊灬快灬高潮了av | av黄色成人在线观看 | 国产日韩欧美在线观看 | 国产无遮挡大学生第一次做 | 亚洲国产精久久久久久久 | 免费一级全黄少妇性色生活 | 在线a精品一区二区 | 色费女人18毛片a级毛片视频 | 九九视频精品全部免费播放 | 国产精品偷伦视频免费观看了 | 精品av国产一区二区三区四区 | 韩国福利一区 | 国产一区二区三区在线免 | 国产91色综合久久麻豆 | 欧美成人精品高清在线播放 | 国产成人无码18禁午夜福利p | 天天免费在线看片 | 午夜福利理论片在线观看播放 | 欧美男生射精高潮视频网站 | 中文av岛国无码免费播放 | 亚洲av色区一区二区三区 | 色综合热无码热国产 | 久久成年 | 波多野结衣乳巨码无在线观看 | 99精品国产高清一区二区三区香蕉 | 97久久综合区小说区图片区 | 日韩国产在线 | 国产一级内射在线视频 | 蜜臀av性久久久久蜜臀aⅴ涩爱 | 日本高清一级婬片a级中文字幕 | 韩国a级情欲片在线观看高清 | 97精品一区二区视频在线观 | 91麻豆精产国品一二三系列产品测评 | 国产区女主播在线观看 | 亚洲欧美日韩综 | 国产一级内射在线视频 | 国产成人精品永久免费视频 | 国产成人啪精品 | 国产av一区二区三区最新精品 | 麻豆精品无人区码一二三 | 中文字幕久热精品 | 午夜亚洲国产 | 亚洲精品综合在线一区二区 | 精品999久久久一级毛片 | 精品视频午夜一区二区 | 91短视 | 成人久久欧亚洲精品无码久久性 | 国产一区二区三区不卡在线看 | 国产精品不卡在线电影 | 中文综合在线观 | 精品国在线观看视频在线播放 | 国产麻豆精品一区二区三区 | 国产99视频精品免费专区 | 69一区二三区好的精华液 | 自拍偷拍中文字幕 | 国产精品无码mv在线观看 | 欧美亚洲视频在线二区 | 国产白嫩精品久久久久久 | 国产女人18毛片水真多18精品 | 亚洲av成人一区二区三区高清 | 色系视频在线观看免费 | 免费一级a毛片在线播放 | 国产av国片精品jk制服 | 丰满人妻被公侵犯中文电影版 | 无遮挡1000部拍拍拍免费观看 | 成人午夜福利 | 国产日韩精品欧美一区 | 亚洲国产精品一区 | 亚洲精品国产拍精品 | 操人人爱| 精品人妻系列无码一区 | 91亚洲视频在线观看 | 成人午夜a级毛片免费 | 成人免费网站久久久 | 午夜av在线播放 | 国产精选秘免费进入竹菊影视 | 国语自产拍无码精品视 | 亚洲av中字免费在 | 日韩美人妻有 | 亚洲成熟丰满熟妇高潮xxxxx | 国产自在现偷国产精品国产日韩 | 欧美精品高清在线观看 | 97无码免费人妻超级碰碰碰碰 | 少妇精品无码一区二区三区 | 午夜dv内射一区区 | 精品国产欧美一区二区三区成人 | 亚洲成av人片一区二区蜜柚 | 久久99精 | 国产a∨天天免费观看美女18 | 日韩经典欧美一区二区三区 | 国产美女做受一级视频 | 亚洲av成人一区二区三区高清 | 色资源av中文无码先锋 | 国产成人无码aa精品一区 | 精品久久久久久无码人妻热 | 在线观看国产精品日韩av | 亚洲va中文字幕久久无码一区 | 国产91免费在线观看 | 91精品国产一区二区无码 | 欧美动漫排行榜推荐 | 欧美日韩一区二区三区视频在线观看 | 日韩精品无码视频免费专区 | 高潮喷水视频一区二区三区 | 99久久精品免费看国产一区二区三 | 亚洲av无码久久寂寞少妇多毛 | 国产午夜精品理论片久久影视 | 99精品国产在热久久无毒 | 精品久久久久久中文字幕专区 | av麻豆出品免费在线观看 | 国产精品青草久久久久福利99 | 尤物久久精品极品 | 成人精品视频一区二区三区 | 国产精品扒开腿做爽爽爽视频 | 91麻豆精品国产91 | 午夜精品久久久99热蜜桃 | 香蕉视频| 成年女人毛片视频喷潮 | 国产在线精品二区 | 91男女无遮挡猛进猛出免费午夜久久 | 国产超碰人人爽人人做人人爱 | 丝瓜视频涩涩屋色多多色版成人 | 日韩东京热无码人妻 | 人妻无码aⅴ中文系列久久免费 | 亚洲av无码乱码精品国产 | 果冻传媒的女主董小宛 | 亚洲欧美日韩一区在线观看 | 国产又黄又大又粗视频 | 无码国产在线 | 人妻少妇一区二区三区 | 色欲国产av | 日本在线视频网 | 人妻少妇白浆一区二区三区 | 91无码国产福利在线观看 | 另类小说| 亚洲日韩中文字 | 亚洲v在线 | 成年片色大黄全免费网站久久 | 91制片厂制作果冻传媒麻豆 | 91精品丝袜国产高跟在线一区 | 亚洲国产精品高清久久久 | 波多野结衣2完整版电影在线 | 亚洲欧美日韩久久 | 亚洲国产精品一区二区不卡 | 日日碰狠狠添天天爽不卡 | 三级精品手机在线 | 日韩av无码久久一区二区 | 国产91高潮流白浆在线播放un | 91嫩草国产线免费观看91 | 国产精品丝袜一区二区三区 | 欧美曰韩一| 中文字幕久久精品一区二区三区 | 欧美日韩一区二区三区人妻 | 色欲av天天a | 国产精品偷伦视频免费观看 | 国产成人av三级在线观看 | 99精品久久久久久久 | 亚洲国产日韩欧美一区二区三区一 | 精品影片在线观看的网站 | 久久99精品国产麻豆不卡 | 亚洲专区av第1页在线 | 狠狠噜天天噜日日噜 | 九一制片厂果冻 | 东京热加勒 | 色综合伊人色综合网站 | 亚洲av日韩av天堂影片精品 | 天美传媒麻豆精东蜜桃 | 婷婷亚洲视频 | 日韩免费一区二区人妻丝袜 | 亚洲av无码精品色午 | 亚洲va国产va欧美 | 中文字幕久久久久人妻 | 亚洲精品成人无码中文毛片不 | 天美传媒免费观看一二三在线 | 国产亚洲成人网在线播放av | 少妇高潮毛片免费观看a片 少妇高潮毛片色欲ava片 | 日本一区二区三区中文字幕 | 国产午夜福利片 | 亚洲第一色片曰本毛片 | 丰满岳乱妇在线观看视频国产 | 97碰碰碰人妻 | 久久成人亚洲香蕉草草 | 成人无码 | 国产成人精品综合在 | 久久99精品久久久久久国产 | 久久99热只 | 亚洲国产精品浪潮久久久av | a性色生活片久久毛片牛牛 a亚洲欧美中文日韩在线v日本 | 91精品国产综合久久久久 | 丰满爆乳一 | 国产成人亚洲视频在线 | 91久久精一区二区三区大全 | 亚洲一区二区影视 | 国产老太睡小伙子视频 | 中文字幕一区二区三区精品 | 日韩精品亚洲精品第一页 | 日本中文一二区有码在线观看 | 国产精品日韩幕无码不卡 | 欧美精品成人a在线观看 | 亚洲av福利天堂在线观看 | 精品一区二区av天堂 | 国产欧美一区二区三区午夜精品 | 亚洲乱色伦图片区小说 | 99re6久| 精品久久久久久无码国产 | 无码久久久久冒白浆 | 九九精品99久久久香蕉 | 99久久国产热无码精品免费久久久久 | 精品国产亚洲第一区二区三区 | 欧美一级特黄大片色欧美精品 | 97视频最新app下载 | 日韩av无码久久一区二区 | 国产原创中文av | 午夜精品视频在线 | 亚洲国产变态另类天堂 | 国产日韩精品一区二区三区在线观 | 国产精品7 | 性色av免费观看 | 国产精品国语刺激对白在线观看 | 精品精品国产自在久久精品 | 国产无码高清在线观看 | 91免费视频成人 | 国产性猛交╳xxx乱大交 | 国产极品粉嫩美女在线播放 | 97亚洲精品无码久久久久久久 | 欧美freesex黑人又粗又大长 | 91久国产在线观看调教 | 无套露脸在线观看 | 国产一级内射在线视频 | 91天堂国产在线在线 | 午夜国产毛片v区一区二区三区 | 丰满少妇被猛烈进入高清播放 | 欧美日韩精品一区二区三区视频在线 | 国产素人搭讪在线观看 | 无人区码卡二卡乱码字幕 | 无遮挡国产高潮视频免费观 | 午夜福到在线a国产4视频 | 人人干操 | 多人乱p杂交公车伦理片手机在线看 | 中文字幕视频二区人妻在线 | 精品动漫福利h视频在线观看 | 亚洲国产无码成人av | 日韩精品免费无码专区 | www深夜成| 久久66热人妻偷产精品9 | 中文字幕一区波多野结衣 | 99久久精品出品国产一区 | 日本中文字幕一区高清在线 | 中文字幕精品一区二区精品 | 91成人爽a毛片一区二区动漫 | 国语精品福利自产拍在线观看 | 国产高清极品美女黄色网站 | 丰满少妇又爽又紧又丰满在线观看 | 97无码超碰中文字幕 | 国产在线播放不卡 | 97精产国品一二三产区 | 国产精品嫩草影院8vv8 | 午夜亚洲成人福利 | 日本久久精品视频 | 亚洲av永久中 | av不卡网站在线免费观看 | 91福利视| 国产香蕉97碰碰久久人人 | 国产一级a爱做片免费看 | 国产老色批免费视 | 狠狠色狠狠 | 中文字幕无码综合一区二区 | 亚洲国产精品va在线观看麻豆 | 97成人无码免费一区二区中文 | 久久成人国产精品青青 | 亚洲成年人电影在线观看 | 亚洲美女人黄网成人女 | 精品久久无码中文 | 欧美孕妇xxxx做受欧美88 | 亚洲午夜国产精品无卡 | 亚洲国产精品va在线观看无 | 欧美精品一区二 | 日本特黄特色aaa大片免费 | 欧美日韩一区二区亚洲 | 亚洲av高清一区二区毛片下卡 | 熟妇人妻av无码一区二区三区 | 97人妻碰碰公开人成视频 | av天堂午夜精品一区 | 国产剧手机免费播放 | 97伦理手机高清免费在线观看 | 欧美亚洲宗合另类在线观看 | av不卡网站在线免费观看 | 午夜国产大片免费观看 | 九九综合九色综合网站 | 国产婷婷色一区二区三区在线 | 国产人a片在 | 动漫成人无码精品一区二区三区 | 91在线无码精品秘国产色多多 | 99爱国产精品免费精品在线 | 午夜福利在线观看大片 | 91久久视频平台是否值得尝试 | 欧美成人家庭影院 | 国产亚洲欧美日韩国产片 | 黑人大战亚洲女在线播放 | 人人爽天天碰天天躁夜夜躁 | 国产免费一级精品视频 | 极品中文字幕国产视频 | 亚洲精品无码成人片久久 | 日韩综合调教网站 | 国产h片无码不卡在线视频 国产h片在线观看视 | 东京热日韩无码高清国产精品 | 国产成人av电影在线 | 国产成人午夜福利免费无码r |