Статьи

Программирование Windows Phone 7.5, часть 3: API стека Exchange

Давайте закончим серию программ для Windows Phone. Первая часть « Приступая к работе » проведет вас через шаги, которые вы должны выполнить, чтобы начать работу с Windows 7.5 (Mango). Вторая часть представляет собой краткое руководство о том , как вы можете легко создавать свои собственные иконки для бренда вашего приложения. Пожалуйста, сначала прочтите их, если вы еще этого не сделали.

Пора нам сделать приложение действительно полезным. Для этого я решил использовать небольшую оболочку для API Stack Exchange, которую я сделал некоторое время назад. Было бы неплохо, если бы у меня было небольшое приложение, позволяющее мне проверить мой профиль StackOverflow.

Вы можете загрузить код для моей оболочки API StackExchange на странице загрузки (2011: статья № 58). Как вы заметите, есть некоторые вещи, которые нам нужно изменить в существующем коде, чтобы он работал на устройстве Windows Phone.

Давайте начнем…

Приложение

Давайте посмотрим на приложение, которое мы собираемся построить. Это простое приложение, которое состоит только из одной страницы (MainPage.xaml). Эта страница содержит сводный элемент управления, состоящий из двух страниц, а именно:

  • Страница профиля : показывает ваш профиль (имя, репутация, значки … и т. Д.)
  • Страница репутации : список обновлений вашей репутации за последние X дней

Картинка стоит тысячи слов, поэтому взгляните на следующие скриншоты.

Приложение StackOverflow

 

Решение

 Давайте запустим Visual Studio 2010 и создадим новое пустое решение под названием StackOverflow. Затем добавьте в него новый проект, используя шаблон проекта приложения Windows Phone, и назовите его StackOverflow.Phone.UI.

Новый проект

Убедитесь, что вы ориентируетесь на ОС Windows Phone 7.1 для всех проектов в этом решении. Visual Studio спросит об этом автоматически при добавлении нового проекта.

ОС Windows Phone 7.1

Теперь вам нужно добавить в проект новую библиотеку классов Windows Phone с именем StackExchange.Api. К настоящему времени ваше решение должно выглядеть следующим образом:

Обозреватель решений


API стека Exchange

Моя маленькая оболочка Stack Exchange API позволяет вам получать эти данные, используя всего несколько строк кода. Нам нужно немного изменить его, чтобы сделать его совместимым с Silverlight для Windows Phone, прежде чем мы сможем его использовать.

Загрузите код (статья № 58: Stack Exchange API) со страницы загрузки . Извлеките архив и скопируйте / вставьте следующие файлы в каталог библиотеки классов StackOverflow.Api.

  • BadgeCount.cs
  • ExtensionMethods.cs
  • ReputationChange.cs
  • StackExchangeApi.cs
  • UnixDateTimeConverter.cs
  • User.cs
  • WrapperObjectAttribute.cs

Затем включите эти файлы в проект StackOverflow.Api.

API стека Exchange

Затем вам нужно добавить пакеты Json.NET и SharpCompress NuGet в эту библиотеку классов.

Пакеты NuGet

Сначала загрузите и установите расширение NuGet, если у вас его еще нет. Вам необходим пакет Json.NET, потому что оболочка Stack Exchange API использует его для сериализации / десериализации данных, а SharpCompress обеспечивает поддержку GZip для Silverlight. В Silverlight нет встроенной поддержки GZip (GZipStream).

Рефакторинг

Если вы строите проект StackOverflow.Api, компилятор выдаст несколько ошибок. Давайте исправим их. Добавив ссылку на сборки SharpCompress, вы уже исправили отсутствующую поддержку GZipStream. Просто убедитесь, что вы включили необходимые пространства имен в файл кода StackExchangeApi.cs.

using SharpCompress.Compressor;
using SharpCompress.Compressor.Deflate;

Также удалите ссылку на пространство имен System.IO.Compression.

Основная проблема текущей реализации заключается в том, что все выполняется синхронно, например, поиск профиля пользователя и изменение его репутации. Silverlight требует от вас много чего делать асинхронно. Получение профиля пользователя следующим способом больше не будет работать:

var api = new StackExchangeApi("your api key");
var user = api.GetUser(893099);

Давайте это исправим. Откройте файл StackExchangeApi и добавьте следующий делегат в класс StackExchangeApi.

public delegate void StackExchangeApiCallback<T>(T data) where T : class, new();

Теперь измените подпись метода GetUser (…) следующим образом:

public void GetUser(int userId, StackExchangeApiCallback<User> callback)
{
    GetStackExchangeObject(String.Format("/users/{0}", userId), callback);
}

При получении профиля пользователя вы заметите, что мы больше не ожидаем, что метод вернет значение. Вместо этого мы передаем ему обратный вызов (наш делегат StackExchangeApiCallback). Этот обратный вызов будет запущен, когда будет получен профиль пользователя. Мы не будем больше этого ждать. Мы ожидаем, что нас проинформируют об этом событии.

Метод GetUser (…) передает обратный вызов реорганизованному методу GetStackExchangeObject (…). Давайте посмотрим, как этот метод был реорганизован для поддержки асинхронных операций.

private void GetStackExchangeObject<T>(string path, StackExchangeApiCallback<T> callback)
    where T : class, new()
{
    var requestUri = ComposeUri(path);
    GetSingleObject(requestUri, callback);
}

private void GetSingleObject<T>(string requestUri, StackExchangeApiCallback<T> callback)
    where T : class, new()
{
    var request = (HttpWebRequest) WebRequest.Create(requestUri);
    request.Method = "GET";
    request.Accept = "application/json";

    request.BeginGetResponse(
        ar =>
            {
                var response = (HttpWebResponse)request.EndGetResponse(ar);
                var json = ExtractJsonResponse(response);
                var data = ParseJson<T>(json).FirstOrDefault();
                callback(data);
            },
        null);
}

Сначала определяется URL-адрес ресурса Stack Exchange, а затем метод GetSingleObject (…) извлекает данные асинхронно. Когда данные поступают, они анализируются и десериализуются, и происходит обратный вызов.

И последнее, но не менее важное: удалите или прокомментируйте закрытый метод GetResponse (…). Это больше не нужно.

Теперь вы можете получить профиль пользователя следующим образом:

private void UserRetrieved(User user)
{
    //...
}

var api = new StackExchangeApi("your api key");
var callback = new StackExchangeApi.StackExchangeApiCallback<User>(UserRetrieved);
api.GetUser(893099, callback);

Когда профиль пользователя будет получен, будет вызван обратный вызов UserRetrieved (…). Он извлекает экземпляр типа User, который содержит профиль пользователя.

Та же проблема (синхронизация с асинхронностью) существует для получения изменений репутации пользователя, но решение аналогично исправлению для получения профиля. Я не буду перечислять это здесь, просто взгляните на исходный код, сопровождающий эту статью. Я также немного расширил оболочку, чтобы она возвращала немного больше данных для профиля пользователя, репутации и т. Д. Вы можете начать со старого кода и выполнить его рефакторинг или просто загрузить готовый код. Здесь я только что показал, как вы можете сделать рефакторинг. Просто повторите это для обновлений репутации, и все готово.

Пользовательский интерфейс

Я не собираюсь концентрироваться на реальном пользовательском интерфейсе. Как вы можете видеть на скриншотах выше, это очень простой интерфейс. Одна страница, содержащая элемент управления, который имеет две страницы. Один для отображения профиля пользователя, а другой для отображения обновлений его репутации.

Страница профиля содержит сетку, в которой перечислены имя пользователя, репутация, количество просмотров, возраст, количество значков и т. Д. Страница репутации содержит ListBox, в котором перечислены обновления репутации пользователя. Загрузите исходный код и посмотрите на код XAML, если вы хотите изучить его, но он действительно простой.

Приложение также содержит панель приложений, которая содержит две иконки. Значок обновления и значок настроек. Я не реализовал страницу настроек, я оставлю это вам в качестве упражнения. Это просто страница настроек, где вы можете ввести свой идентификатор переполнения стека. Пример кода использует жестко идентифицированный идентификатор. Не стесняйтесь улучшить это и реализовать страницу настроек.

Панель приложений

Код для приложения довольно прост. Просто добавьте ссылку на библиотеку StackOverflow.Api из проекта пользовательского интерфейса. Просто создайте экземпляр класса StackExchangeApi.

public partial class MainPage : PhoneApplicationPage
{
    private StackExchangeApi _api;

    // Constructor
    public MainPage()
    {
        InitializeComponent();

        this._api = new StackExchangeApi("your api key");

        Loaded += MainPage_Loaded;
    }

    //...
}

После этого действительно просто загрузить данные. Просто создайте обратный вызов и вызовите метод GetUser (…).

void MainPage_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
    var callback = new StackExchangeApi.StackExchangeApiCallback<User>(UserRetrieved);
    this._api.GetUser(893099, callback);

}

void UserRetrieved(User user)
{
    Dispatcher.BeginInvoke(() =>
                                {
                                    DisplayName.Text = user.DisplayName;
                                    // ...
                                    BronzeBadges.Text = user.BadgeCounts.Bronze.ToString();
                                });
}

Просто убедитесь, что вы получили доступ к элементам управления в потоке пользовательского интерфейса, поэтому вызовите Dispatcher.BeginInvoke (…).

Вот и все, что нужно для быстрого создания демонстрационного демонстрационного приложения Windows Phone с использованием Stack Exchange API. Если вам нужна дополнительная информация о том, как использовался этот API, прочтите API Stack Exchange, которое я написал пару месяцев назад.

Вы можете скачать исходный код, сопровождающий эту статью, со страницы загрузки. Если у вас есть какие-либо вопросы или предложения, напишите мне по электронной почте или оставьте комментарий.

Источник: http://cgeers.com/2011/12/03/programming-windows-phone-7-5-part-3-stack-exchange-api/