Новые книги

Master Android from first principles and begin the journey toward your own successful Android applications!

Dear Reader,

First, welcome to the world of Android! We’re entering a new era of mobile application development, one marked by open platforms and open source, to take ‘walled gardens’ and make them green houses for any and all to participate in. Android is relatively easy for developers, and I believe that this innovation will help generate a large ecosystem of developers and consumers within a very short time. This means that budding developers such as yourself will have many opportunities to design and build your own applications and you’ll have a huge and hungry customer base.

Second, welcome to the book! Its purpose is to start you on your way with building Android applications, and to help you master the learning curve. Android is already a rich framework, comparable in many ways to the richness Android of desktop Java environments. This means that there is a lot of cool stuff for you to pick up along your journey in order to create the slickest, most useful apps Android you can imagine.

The source code for the code samples in this book is all available from the Apress site, so you can stay as hands-on and practical as you like while I introduce you to the core of Android, and invite you to experiment with the various classes and APIs we’ll be looking at. By the time you’ve finished this book, you’ll be creating your own Android applications and asking yourself what your next great application will be…!

Enjoy!

Mark Murphy
Сразу после выхода в свет эта книга заняла первые места на Amazon среди книг по маркетингу и клиентскому сервису. Формирование источника регулярной выручки для компании – важная задача каждого предпринимателя. Благодаря разнообразию разновидностей бизнес-моделей на основе подписки для каждой отрасли можно найти подходящий вариант. Подписчики в любом случае намного ценнее для компании, чем обычные покупатели.

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

На русском языке публикуется впервые.

Ожидание загрузки изображений

Ожидание загрузки изображений

Оглавление

Растровые изображения
Загрузка и рисование
Класс Image
Ожидание загрузки
Видео
Аплет CDRotation

Как мы уже говорили в наших предыдущих статьях, загрузка изображений из сети Internet - длительный процесс, который в среднем идет со скоростью 1 Кбайт в секунду. Поэтому изображения загружаются навигатором в отдельной задаче. При этом метод getImage только создает объект класса Image, а метод drawImage инициирует загрузку изображения и рисует его. Причем если файл изображения имеет большую длину, он будет появляться в окне аплета постепенно по мере загрузки.

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

Есть ли способ определить, когда изображение будет загружено полностью?

Есть, и причем целых два. Один из них связан с использованием класса MediaTracker, специально предназначенного для этой цели и достаточно удобного в использовании, другой основан на переопределении одного из методов интерфейса ImageObserver.

Применение класса MediaTracker

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

Как это сделать?

Обычно метод init аплета создает объект класса MediaTracker с помощью конструктора и добавляет в него все изображения, загрузки которых необходимо дождаться.

Создание объекта класса MediaTracker

Объект класса MediaTracker создается следующим образом:

MediaTracker mt;
mt = new MediaTracker(this);

Конструктору класса MediaTracker передается ссылка на компонент, для которого необходимо отслеживать загрузку изображений. В данном случае это наш аплет, поэтому мы передаем конструктору значение this.

Добавление изображений в объект класса MediaTracker

Далее метод init должен создать все необходимые объекты класса Image и добавить их в объект MediaTracker методом addImage. Ниже мы показали фрагмент кода, в котором выполняется добавление трех изображений:

Image img1;
Image img2;
Image img3;
img1 = getImage(getCodeBase(), "pic1.gif");
img2 = getImage(getCodeBase(), "pic2.gif");
img3 = getImage(getCodeBase(), "pic3.gif");
mt.addImage(img1 , 0);
mt.addImage(img2 , 0);
mt.addImage(img3 , 0);

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

Ожидание загрузки добавленных изображений

Для того чтобы убедиться, что все изображения загружены, вы можете воспользоваться методом waitForAll. Этот метод инициирует загрузку изображений, а также задержит выполнение вызвавшего потока до момента полной загрузки всех изображений, добавленных в объект класса MediaTracker:

try
{
  mt.waitForAll();
}
catch (InterruptedException ex)
{
}

Обратите внимание, что метод waitForAll может создавать исключение InterruptedException. Это исключение возникает, если по какой-либо причине процесс ожидания прерывается.

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

Другие методы класса MediaTracker

Какие другие полезные методы, кроме методов addImage и waitForAll есть в классе MediaTracker?

public boolean waitForAll(long ms);

Метод waitForAll с параметром ms позволяет выполнять ожидание в течение заданного времени. Время ожидания задается в миллисекундах. При этом если за указанное время все изображения были успешно загружены, метод waitForAll возвращает значение true, если нет - false.

Вариант метода checkAll с параметром load позволяет проверить, завершилась ли загрузка отслеживаемых изображений:

public boolean checkAll(boolean load);

Если значение параметра load равно true, метод инициирует загрузку изображений.

Если при добавлении изображений методом addImage вы использовали второй параметр этого метода для присваивания разным группам изображений различные идентификаторы, то с помощью метода checkID можно дождаться завершения загрузки отдельной группы изображений:

public boolean checkID(int id);

Есть также вариант этого метода, позволяющий проверить загрузку группы изображений с заданным идентификатором:

public boolean checkID(int id, boolean load);

Метод waitForID с параметрами id и ms позволяет выполнять ожидание загрузки группы изображений с заданным идентификатором в течении указанного периода времени:

public boolean waitForID(int id, long ms);

Класс MediaTracker предоставляет также возможность прослеживать сам процесс загрузки всех добавленных в него изображений или отдельных групп изображений с помощью методов statusAll и statusID:

public int statusAll(boolean load);
public int statusID(int id, boolean load);

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

Методы statusAll и statusID возвращают значение, составленное из отдельных битов состояния при помощи логической операции ИЛИ. Ниже мы перечислили эти биты состояния и привели их краткое описание.

Биты состояния Описание
MediaTracker.LOADING Один или несколько отслеживаемых файлов продолжают загружаться
MediaTracker.ABORTED Загрузка одного или нескольких файлов была прервана
MediatTracker.ERRORED При загрузке одного или нескольких файлов произошла ошибка
MediaTracker.COMPLETE Загрузка всех отслеживаемых файлов произошла полностью и успешно

Еще четыре метода, определенных в классе MediaTracker, связаны с обработкой ошибок:

public boolean isErrorAny();
public boolean isErrorID(int id);
public Object[] getErrorsAny();
public Object[] getErrorsID(int id); 

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

Методы getErrorsAny и getErrorsID возвращают массив объектов, при ожидании загрузки которых произошла ошибка. Первый из этих методов возвращает массив для всех отслеживаемых объектов, второй - только объектов из заданной группы.

Применение интерфейса ImageObserver

Второй способ ожидания завершения процесса загрузки изображений связан с интерфейсом ImageObserver:

Биты флагов для параметра infoflags метода imageUpdate

public final static int ABORT; 
public final static int ALLBITS; 
public final static int ERROR; 
public final static int FRAMEBITS; 
public final static int HEIGHT; 
public final static int PROPERTIES;
public final static int SOMEBITS; 
public final static int WIDTH; 

Метод imageUpdate

public abstract boolean
  imageUpdate(Image img, int infoflags,
  int x, int y, int width, int height);

Как видите, в интерфейсе ImageObserver определен единственный метод imageUpdate и набор битовых флагов для этого метода.

Класс Component, от которого происходит класс Applet, реализует интерфейс ImageObserver:

public abstract class java.awt.Component
  extends java.lang.Object
  implements java.awt.image.ImageObserver
{
  . . .
}

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

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

Процедура ожидания загрузки изображений достаточно проста.

Прежде всего, аплет должен передать в последнем параметре методу drawImage ссылку на интерфейс ImageObserver, который будет применяться для отслеживания процесса загрузки:

g.drawImage(Img, x, y,
  width, height, this);

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

Ниже мы привели возможный вариант реализации этого метода:

public boolean imageUpdate(
  Image img, int flags,
  int x, int y, int w, int h)
{
  // Проверяем, все ли 
  // биты изображения загружены
  fAllLoaded = ((flags & ALLBITS) != 0);

  // Если все, перерисовываем окно
  if(fAllLoaded)
    repaint();

  // Если все биты загружены,
  // дальнейшие вызовы
  // метода imageUpdate не нужны
  return !fAllLoaded;
}

Через первый параметр img методу imageUpdate передается ссылка на изображение, загрузка которого отслеживается.

Параметр flags отражает состояние процесса загрузки.

Через остальные параметры x, y, w и h передаются, соответственно, координаты и размеры изображения.

Основное, что должен делать метод imageUpdate для отслеживания процесса загрузки - это проверять флаги flags, дожидаясь установки нужных флагов.

Флаги определены следующим образом:

public final static int WIDTH;
public final static int HEIGHT = 2;
public final static int PROPERTIES = 4;
public final static int SOMEBITS = 8;
public final static int FRAMEBITS = 16;
public final static int ALLBITS = 32;
public final static int ERROR = 64;
public final static int ABORT = 128;

Ниже мы привели краткое описание перечисленных флагов.

Флаг Описание
WIDTH Изображение загружено настолько, что стала доступна его ширина. Значение ширины изображения можно получить из параметра w метода imageUpdate
HEIGHT Аналогично предыдущему, но для высоты изображения. Высоту изображения можно получить из параметра h метода imageUpdateimageUpdate
PROPERTIES Стали доступны свойства изображения, которые можно получить методом getProperty класса Image. В нашей книге мы опустили описание этого метода
SOMEBITS Стали доступны биты изображения для рисования в масштабе. Через параметры x, y, h и w передаются координаты и размеры прямоугольной области, которая ограничивает загруженную часть изображения
FRAMEBITS Загружен очередной фрейм изображения, состоящего из нескольких фреймов. Параметры x, y, h и w следует игнорировать
ALLBITS Изображение загружено полностью. Параметры x, y, h и w следует игнорировать
ERROR При загрузке произошла ошибка
ABORT Загрузка изображения была прервана или отменена

Анализируя состояние флагов, метод imageUpdate может следить за ходом загрузки изображений, отображая, например, процент завершения процесса загрузки или выполняя какие-либо другие действия.

Если вам нужно только дождаться завершения процесса загрузки, достаточно использовать флаг ALLBITS. Для проверки ошибок воспользуйтесь флагами ERROR и ABORT.