Редактировать
Извините, я не заметил, что вы не хотите поддерживать разные версии библиотеки. В этом случае нет никакого способа - когда FP обрабатывает байт-код SWF и когда он находит неизвестную ссылку, он выдает VerifyError. Конечно, вы можете использовать getDefinitionByName()
и динамический доступ, но он очень медленный.
Чтобы минимизировать количество отдельно поддерживаемого кода, вы можете использовать SWC с основными функциями и SWF с функциями, зависящими от версии, поэтому на этапе инициализации основной класс вашей библиотеки проверит версию FP и загрузит соответствующий SWF.
Это называется динамическим связыванием, и есть способ:
Создание интерфейса для всех функций, зависящих от версии проигрывателя (public interface MyInterface...
). Этот интерфейс не должен содержать ссылок на зависимые от версии API. Скомпилируйте этот интерфейс (это может быть только один файл .as) в SWC (пусть это будет lib-intf.swc
).
Создание двух независимых реализаций этого интерфейса; первый будет использовать новые API, второй - нет (он может быть просто заполнителем, но также может быть альтернативной реализацией). Позже нам нужно скомпилировать эти реализации в SWF, поэтому нам нужны основные классы, расширяющие Sprite
. Самый простой способ сделать это - заставить эти основные классы реализовать наш интерфейс (т. Е. public class MyImplementationA extends Sprite implements MyInterface...
, и то же самое для MyImplementationB
). Они будут просто пустыми Sprites
, но будут содержать методы интерфейса.
Скомпилируйте эти две реализации независимо в отдельные SW F s (lib-a.swf
и lib-b.swf
). При компиляции включите lib-intf.swc
в качестве внешней библиотеки (-external-library-path
параметр компилятора или "внешний" тип связи в IDE).
Теперь, при компиляции вашего корневого приложения, включите lib-intf.swc
как обычную библиотеку (-library-path
параметр компилятора или тип ссылки «объединены в код» в IDE). Не включайте классы, зависящие от версии. Таким образом, в корневом приложении у вас будут только ссылки на интерфейс, который не зависит от версии. Когда ваше приложение запустится, проверьте версию FP и, в зависимости от этого, загрузите соответствующий SWF, используя класс Loader. Вам нужно будет загрузить его в основной домен приложения, а не в дочерний (это опция по умолчанию; более подробная информация ).
Когда SWF загружен, приведите его к интерфейсу: var versionDependentImpl:MyInterface = loader.content as MyInterface
. Помните, что основные классы наших SWF-файлов реализуют MyInterface
, поэтому это приведение будет работать.
Вот и все - теперь вы можете использовать свою реализацию: versionDependentImpl.someMethod()
. Конечно, someMethod
должно быть определено в MyInterface
.
Итак, хитрость в том, чтобы динамически загружать реализацию из SWF-файла. Хотя корневое приложение ничего не знает о классах внутри этого SWF-файла, мы можем использовать методы его основного класса, потому что мы заставили его реализовать интерфейс, который мы скомпилировали в корневое приложение.
Этот подход является масштабируемым: например, вы можете определить основной интерфейс, у которого есть методы, которые возвращают другие интерфейсы. Вы даже можете включить конкретные классы, которые совместно используются реализациями, в lib-intf.swc
, если они не используют зависимые от версии API.