|
|
« Предыдущая тема | Следующая тема » |
Опции темы | Опции просмотра |
|
|
|||||
Et cetera
Регистрация: Sep 2002
Сообщений: 30,784
|
Цитата:
getResource синхронный, загрузка отдельно. А вообще, вот у Блуда оно самое: http://code.google.com/p/blooddy/sou...prite.as?r=270 |
|
|||||
блогер
Регистрация: Jun 2005
Адрес: Господи пожалуйста не Новосибирск
Сообщений: 6,598
Записей в блоге: 17
|
Немного сигнатуры отличаются =)
Спасибо за ссылку )
__________________
Тут мужик танцует и поёт про флэш |
|
|||||
Регистрация: Nov 2010
Сообщений: 497
|
То, что менеджер превращается в обертку, как раз вполне естественно. И что-то другое получить как раз достаточно сложно. Далее по порядку, так как разработка этого ResourceManager очень показательна с точки зрения процесса разработки.
Шаг первый. Формулировка задачи. Задача была сформулирована в первом сообщении. Плюс был приведен сценарий использования и API для него (ну и 99% других подобных случаев). Здесь же можно сформулировать интерфейс ResourceManager исходя из тех мест, где он применяется. Но ни в коем случае не из того, как он реализован внутри! Шаг второй. Формализация задачи. Собственно, что должен делать мендежер? 1. Загружать ресурсы (транспорт по сети). 2. Хранить уже загруженные ресурсы. 3. Конвертировать "символические" имена в абсолютные. 4. Предзагружать ресурсы по требованию. 5. Предзагружать ресурсы при старте/инициализации. Шаг третий. Проектирование и реализация. Очень важный здесь инструмент - Single Responsibility Principle - каждый "элемент" имеет ровно одну ответственность. Ответственность 3 элементарно реализуется отдельным классом (методом, если не пугают замыкания!). Ответственность 1 - уже реализована (транспорт, тот же BulkLoader и т.п.). Ответственность 5 при желании делается внешней с помощью отдельного метода. Остаются хранение и предзагрузка. Само по себе "хранение" уже реализовано - это обычные динамические объекты. Остается - предзагрузка ресурсов. Она зависит от хранения (в любом случае). Ее то и нужно реализовать. Плюс для ее реализации в любом случае нужно будет использовать какое-то хранилище данных. Реализуем (делегируя все, что можно). Смотрим, что получилось. Получилась "получение данных и хранение результатов запросов" по фунциям. Т.е. кэш . Или обертка поверх протокола получения данных. Гордо называем то, что у нас вышло Cache, по его основной функциональности и кладем в библиотеку. Авось, пригодится еще. Шаг четвертый. Собираем все вместе. На предыдущем шаге мы научились решать отдельные "подзадачи". Теперь нужно решить исходную задачу. Фактически дословно пишем то, что хотелось изначально: public function createResourceManager(transport : SomeLoader, config : XML) : ResourceManager { const modRewrite : SomeLoader = createRewritingTransport(config, transport); //resp. 2, transport - resp. 1 const result : ResourceManager = new ResourceManagerOfCache(new Cache(modRewrite)); // resp 3, resp. 4 result.preloadResources(getInitialyPreloadedResources(config), function() : void {}); //resp 5 return result; } Шаг пятый. Пожинаем плоды. У нас раньше получилась хорошая и достаточно удобная декомпозиция и удобный кэш. Теперь его можно использовать где-нибудь в другом месте. Например, можно кэшировать профили игроков социальной сети. В менеджер это не очень вписывалось, но у нас же есть кэш. Для усложнения предположим, что раньше SomeLoader получал ресурсы и обработчики по одному. В социальной сети же из соображений оптимальности лучше запрашивать и загружать профили пачками. Т.е. нужно изменить интерфейс "поставшика ресурсов" кэша на интерфейс со множественной загрузкой. Меняем интерфейс. Параллельно делаем загрузчик со "множественными" запросами поверх загрузчика с одиночными запросами (он достаточно прямолинеен). Меняем создание менеджера. Затем собираем кэш для социальной сети. Итого получаем: public function createResourceManager(transport : SomeLoader, config : XML) : ResourceManager { const modRewrite : SomeLoader = createRewritingTransport(config, bulkLoader); const bulkLoader : BulkLoader = new BulkLoaderOfSimpleLoader(modRewrite); const result : ResourceManager = new ResourceManagerOfCache(new Cache(bulkLoader)); result.preloadResources(getInitialyPreloadedResources(config), function() : void {}); return result; } public function createProfilesCache(profilesLoader : BulkLoader) : Cache { return new Cache(profilesLoader); } На практике такой детализации с самого начала не происходит. Не заводится лишних интерфейсов и т.п. А вот детальное разделение функциональности все равно делается. В результате при необходимости дальнейших изменений новые интерфейсы заводятся и затем просто по-другому сочетается старая функциональность. Еще отмечу, что "переписывание" имен (modRewrite) можно было делать и "снаружи" кэша. Принципиально это ничего не изменяет, так как эта функциональность не зависит от других требуемых. Меняется только удобство написания обертки (может количество методов отличаться, например). |
|
|||||
буду краток
модератор форума
Регистрация: Sep 2003
Адрес: Ближайшее Замкадье
Сообщений: 3,110
Записей в блоге: 28
|
2maxkar
Блин, хорошо всё написано, но как-то "профакториально". Видно человека с большим java-бэкграундом) be simple
__________________
Отряд Котовскага |
|
|||||
блогер
Регистрация: Jun 2005
Адрес: Господи пожалуйста не Новосибирск
Сообщений: 6,598
Записей в блоге: 17
|
@maxkar, спасибо за консультацию =)
В целом, примерно это у меня и вырисовывается, только классы немного по другому сгруппированы. Что скажете по поводу моего текущего положения? ResouceManager — собственно, всем заправляет ResourceInfo — набор статических констант, вроде public static const IMAGE_TYPE:uint = 0; public static const SWF_TYPE:uint = 1; public static const XML_TYPE:uint = 2; public static const SOUND_TYPE:uint = 3; ResouceItemData — value object с вот такими полями: public var type:uint; public var request:URLRequest; public var autoPreload:Boolean; public var data:*; public var loaded:Boolean = false; public var loadStarted:Boolean = false; public var soundLoaderContext:SoundLoaderContext; public var securityDomain:SecurityDomain; public var name:String; public var definitionName:String; ResourceLoader — непосредственная обёртка над BulkLoader, которая качает файлы и заносит их в ResourceDataProvider. Он же вызывает callback`и, когда "группа" полностью готова к работе. (callback`и он получает от ResourceManager`а).
__________________
Тут мужик танцует и поёт про флэш |
|
|||||
Регистрация: Nov 2010
Сообщений: 497
|
Нормально.
На мост ResourceDataProvider вроде бы не тянет, хотя я в паттернах плохо разбираюсь. Это всего лишь интерфейс (ну или класс, в данном случае без разницы), необходимый для работы ResourceManager, обычная "внешняя зависимость". Если у нее удачный конструктор, то его тоже менять не придется, достаточно будет новый парсер данных написать . Лишние данные в ResourceItemData не страшны. Даже на 100 картинок там всего пара килобайт лишних наберется. Не критично. Если хочется попробовать экономить, можно динамические объекты передавать для разных типов, но в общем то совсем не нужно. Еще вариант - ResourceItemData могут создаваться динамически при запросе. Например, когда в XML указывается только путь к корневому каталогу картинок, а "именем" картинки является ее относительный путь. Ну а для callback'ов все нужно грамотно реализовать. Там как раз самые большие сложности вроде: В идеале ресурсы 2 и 4 должны быть загружены 1 раз, callback3 должен быть вызван один раз и только после того, когда ресурсы 2 и 4 готов (остальных можно не дожидаться, можно - дожидаться). |
|
|||||
Et cetera
Регистрация: Sep 2002
Сообщений: 30,784
|
Psycho Tiger, по сути bundleName и есть url до файла)
|
|
|||||
блогер
Регистрация: Jun 2005
Адрес: Господи пожалуйста не Новосибирск
Сообщений: 6,598
Записей в блоге: 17
|
@maxkar, да-да, в callback`ах все сложности. Вчера пересмотрел взгляды на подход реализации callback`ов. Теперь ResourceItem хранит только то, что из файла надо тянуть, и тянет ссылку на ResourceFile. ResourceFile extends EventDispatcher, что даёт красивую картинку загрузок. ResourceGroup получает список файлов Vector.<ResourceFile>, которые надо загрузить. ResourceGroup смотрит, кто загружен, а кто ещё нет, и ждёт загрузки всех остальных, после чего вызывает callback. В итоге, экземпляров класса стало ещё больше, но картина стала ещё правильней =)
@etc, расскажи пожалуйста как у вас там загрузка происходит, я найти не могу. (лучше всего на пальцах, без кода)
__________________
Тут мужик танцует и поёт про флэш |
|
|||||
Et cetera
Регистрация: Sep 2002
Сообщений: 30,784
|
Psycho Tiger, да там всё просто, ResourceSprite дёргает свой ResourceManager, из него и грузит.
|
|
|||||
блогер
Регистрация: Jun 2005
Адрес: Господи пожалуйста не Новосибирск
Сообщений: 6,598
Записей в блоге: 17
|
Это я понял =)
Интересует именно сама прогрузка. Как ResourceManager решает, что нужно что-то прогрузить? По запросу от ResourceSprite или контроллер, создавая вью всегда гарантирует что ресурсы загружены? Когда идёт загрузка ResourceSprite ожидает окончания, или создаётся после окончания загрузки? Как определяется, какие ресурсы нужны этому ResourceSprite?
__________________
Тут мужик танцует и поёт про флэш |
Часовой пояс GMT +4, время: 11:05. |
|
« Предыдущая тема | Следующая тема » |
|
|