API Android включает в себя более 100 элементов управления для реализации пользовательского интерфейса, наследуемых от базового вида View. Далеко не все из них используются в реальных приложениях, но но даже с учётом данного факта в текущей версии DroidScript используется порядка 40% данных объектов с относительно ограниченной функциональностью. Как можно увеличить количество объектов и методов для работы с ними? Существует три варианта:
Первые два варианта не подходят, если необходимо реализовать недостающую функциональность сейчас и нет возможности ждать или изучать Java. Остаётся последний вариант, который имеет следующие преимущества: во-первых, написание плагина под DroidScript - относительно простая задача, основывающаяся на шаблонах, во-вторых, в процессе работы над ней появляется возможно познакомиться с возможностями Android API и програмированием на Java под Android. В этом как раз и состоит идея, заложенная в DroidScript изначально, - начать изучение программирования мобильных приложений с простого языка JavaScript и после, при желении, углубиться в Java для более глубокого дальнейшего изучения данного направления.
Основная трудность при разработке плагина расширения заключается в понимании отличий при работе JavaScript и Java и выборе формата обмена данными между ними, между JavaScript и Java. В отличие от JavaScript для успешного выполнения команд Java-плагину необходимо знать тип данных. Если методу, имеющему аргумент одного типа (например, int - целое) передать параметр другого типа (String - строкового, Boolean - логического, Float - вещественного), то при выполнении метода возникнет исключение, и он, соответственно, не будет выполнен. Тип параметров можно указывать в самом плагине, либо передавать их вместе с данными при вызове метода из JavaScript. Первый вариант ограничивает гибкость работы. Второй вариант свободен от данного ограничения, но требует от пользователя дополнительной работы - указания типа передаваемых параметров.
Плагин расширения можно реализовать с разной степенью гибкости в работе: с доступом через методы или строковые команды, с реализацией универсальных методов или методов для каждого объекта, с обращением к явным или неявным (динамически созданным) методам.
В идеальном случае неплохо было бы генерировать новые объекты и методы динамически, как в JavaScript, но реализовать полную автоматизацию на Java весьма непросто, да и не нужно, так как в любом случае придётся вручную задавать тип каждого параметра, передаваемого в плагин из приложения на JavaScript.
Расмотрим преимущества и недостатки каждого из указанных выше подходов.
Доступ к функциям плагина посредством методов
Для доступа к функциям плагина можно использовать либо интерфейсные функции плагина, либо команды. В первом случае для каждой функции плагина необходимо создать интерфейсную функцию, например, если необходимо реализовать функцию поворота объекта, то создаём две функции:
private void SetRotation( int p_angle ); // приватная функция плагина
this.SetRotation = function( obj, angle ); // интерфейсная функция, которой передаётся объект и значение угла поворота
Преимущество этого способа состоит в том, что, во-первых, в DroidScript-приложении можно получить список методов плагина и понять функциональность плагина, а ,во-вторых, данный метод является универсальным, поскольку может работать с любым переданным из приложения объектом, который допускает вращение.
Недостатком этого варианта является необходимоть:
Доступ к функциям плагина посредством команд
Командный способ доступа к функциям плагина обладает большей гибкость. В этом случае можно использовать один интерфейсный метод, в котором передавать команду, например:
this.runMethodNot (obj, "SetRotation", angle);
В этом случае можно реализовать безрегистровое сравнение команд, что избавит пользователя от необходимости задания названия команды с учетом регистра.
Недостатком этого способа является невозможность
Универсальные методы
Этот вариант интересен тем, что позволяет выполнять действия без привязки к конкретному типу объекта. Универсальный метод передаёт плагину объект, который в коде плагина приводится к объекту, позволяющему такое действие:
this.plg.RunCommand (obj, "RunCommand", angle); // интерфейсная функция
private void runMethodNot (Object obj, Bundle b){
View _view = (View)obj;
}
Недостатком универсальных методов является невозможность ограничения функциональности для того или иного объекта. Для чего органичивать функциональность? Например, в целях получения коммерческой выгоды, когда бесплатно предоставляется ограниченная функциональность объекта, а при покупке - полная.
Универсальные методы можно группировать в разных объектах, например, добавлять непосредственно к объекту плагина и ли его полям,например, utils.
Методы объектов
В этом случае можно гибко изменять функциональность объектов путём определения для каждого из них своего набора интерфейсных методов, перечень которых можно получить программно.
Выше были описаны способы при которых функции плагина во внутренней части определяются статически и должны существовать в момент обращения к ним. Недостатком такого способа определения методов яляется то, что для расширения функциональности плагина и добавления в него новых методов придётся каждый раз вносить изменения в код и пересобирать плагин. Существенно уменьшить количество таких дополнительных действия можно путём динамической генерации объектов и методов с использованием рефлексии. При этом подходе мы не добавляем методы вручную, а расширяем функциональность генератора методов с тем, чтобы он мог работать с возможно большим числом методов Android API. Динамическая разработка в Java на порядок сложнее статичной, но благодаря ей получается весьма гибкое решение без необходимости совершения большого количества рутинной работы.
Выбор варианта реализации плагина зависит от конкретной задачи. Если нужно реализорвать функциональность поворота объектов, то быстрее и проще всего реализовать это статично с использованием командного управления. Если же вы хотите дополнить DroidScript функциональностью в полном объеме, то необходимо использовать динамическое программирование, разбив его на более простые подзадачи, на чём мы и остановимся.