Главная » Разработка для Windows Phone 7 » Изображения из Интернета

0

Одна из самых замечательных возможностей, предоставляемых элементом Image – возможность задания URL в качестве значения свойства Source, как в данном проекте на Silverlight:

Проект Silverlight: SilverlightWebBitmap Файл: MainPage.xaml (фрагмент)

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

<Image Source="http://www.charlespetzold.com/Media/HelloWP7.jpg" /> </Grid>

И вот что получается:

Несомненно, это довольно просто, и извлечение изображений из Интернета, вместо того чтобы сохранять их в приложении, конечно же, намного сокращает размер исполняемого файла. Но нет никакой гарантии, что приложение, выполняющееся под управлением Windows Phone 7, будет иметь подключение к Интернету, не говоря уже о других проблемах, связанных с загрузкой файлов. Элемент Image имеет два события, ImageOpened (Изображение открыто) и ImageFailed (Ошибка загрузки изображения), которые могут использоваться для определения успешности или сбоя загрузки.

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

В XNA загрузить растровое изображение из Интернета не так просто, но .NET-класс WebClient (Веб-клиент) делает все относительно безболезненно. С этим классом несколько проще работать, чем с общепринятым альтернативным вариантом (HttpWebRequest (Веб-запрос HTTP) и HttpWebResponse (Веб-ответ HTTP)), и часто он является предпочтительным выбором для загрузки единичных элементов.

WebClient может использоваться для загрузки либо строк (как правило, XML-файлов), либо бинарных объектов. Фактическая передача выполняется асинхронно. Когда файл передан,

WebClient вызывает метод, чтобы обозначить успешное завершение загрузки или ее сбой. Этот вызов метода происходит в потоке логики выполнения приложения, так что вы пользуетесь преимуществами асинхронной передачи данных без явной обработки вторичных потоков.

Чтобы использовать WebClient в приложении на XNA, понадобиться добавить ссылку на библиотеку System.Net. Для этого в Solution Explorer под именем проекта щелкните правой кнопкой мыши References (Ссылки) и выберите Add Reference (Добавить ссылку). В таблице .NET выберите System.Net. (приложения на Silverlight получают ссылку на System.Net автоматически.)

Файл Game1.cs проекта XnaWebBitmap также требует директивы using для пространства имен System.Net. Данное приложение описывает те же поля, что и предыдущая программа:

Проект XNA: XnaWebBitmap Файл: Game1.cs (фрагмент, демонстрирующий поля)

public class Game1 : Microsoft.Xna.Framework.Game {

GraphicsDeviceManager graphics; SpriteBatch spriteBatch; Texture2D helloTexture; Vector2 position;

}

Метод LoadContent создает экземпляр WebClient, задает метод обратного вызова и затем инициирует передачу:

Проект XNA: XnaWebBitmap Файл: Game1.cs (фрагмент)

protected override void LoadContent() {

spriteBatch = new SpriteBatch(GraphicsDevice); WebClient webClient = new WebClient();

webClient.OpenReadCompleted += OnWebClientOpenReadCompleted; webClient.OpenReadAsync(new

Uri("http://www.charlespetzold.com/Media/HelloWP7.jpg")); }

Метод OnWebClientOpenReadCompleted (При завершении операции открытия-чтения Веб- клиентом) вызывается, когда файла полностью загружен. Возникнет желание проверить, не была ли отменена загрузка, и не возникло ли ошибки. Если все в порядке, свойство Result (Результат) аргументов события будет типа Stream (Поток). Этот Stream можно использовать со статическим методом Texture2D.FromStream (Из потока) для создания объекта Texture2D:

Проект XNA: XnaWebBitmap Файл: Game1.cs (фрагмент)

void OnWebClientOpenReadCompleted(object sender, OpenReadCompletedEventArgs args) {

if (!args.Cancelled && args.Error == null) {

helloTexture = Texture2D.FromStream(this.GraphicsDevice, args.Result);

Viewport viewport = this.GraphicsDevice.Viewport;

position = new Vector2((viewport.Width – helloTexture.Width) / 2,

(viewport.Height – helloTexture.Height) / 2);

}

}

Метод Texture2D.FromStream поддерживает форматы JPEG, PNG и GIF.

По умолчанию значение свойства AllowReadStreamBuffering (Разрешить буферизацию потока чтения) объекта WebClient равно true. Это означает, что событие OpenReadCompleted (Открытие-чтение завершено) будет формироваться, только когда весь файл будет полностью загружен. Объект Stream, доступный в свойстве Result, фактически является потоком в памяти, однако, это экземпляр внутреннего класса библиотек .NET, а не самого MemoryStream (Поток в памяти).

Если задать AllowReadStreamBuffering значение false, свойство Result будет сетевым потоком. Класс Texture2D не позволит выполнять чтение из этого потока в основном потоке выполнения программы.

Как правило, метод LoadContent производного от Game класса вызывается до первого вызова метода Update или Draw, но важно помнить, что между вызовами LoadContent и OnWebClientOpenReadCompleted пройдет масса времени. В течение этого времени выполняется асинхронное чтение, но класс Game1 продолжает выполняться, как обычно, вызывая Update и Draw. Поэтому попытка доступа к объекту Texture2D должна выполняться, только когда точно известно, что он действителен:

Проект XNA: XnaWebBitmap Файл: Game1.cs (фрагмент)

protected override void Draw(GameTime gameTime) {

GraphicsDevice.Clear(Color.Navy);

if (helloTexture != null) {

spriteBatch.Begin();

spriteBatch.Draw(helloTexture, position, Color.White); spriteBatch.End();

}

base.Draw(gameTime);

}

В реальном приложении желательно также предусмотреть некоторое уведомление пользователя в случае, если растровое изображение не может быть загружено.

Источник: Чарльз Петзольд, Программируем Windows Phone 7, Microsoft Press, © 2011.

По теме:

  • Комментарии