Создание пакета Dart для публичного использования.

Не более чем через четыре дня после публикации моей статьи о пакете Dart, реклама, который использовал собственный плагин Google, firebase_admob, для добавления рекламы в ваше приложение Flutter, Я начал писать еще одну статью примерно на ту же тему. Мне не понравился пакет Dart, который вы видите. Итак, почему это было?

Ну, потому что, как я объяснил в конце моей предыдущей статьи Добавьте рекламу в свое приложение в мгновение ока!, Есть некоторые вещи, которые необходимо учитывать при предоставлении программы для общественного потребления. Я намекнул, что есть еще нерешенные вопросы, которые необходимо решить. Что ж, четыре дня спустя к ним обратились. Опять же, это касается пакета Dart реклама. Я сделал это лучше. Вот почему.

Для общественного потребления

Я сделал его лучше для использования в продакшене с неизвестными мобильными приложениями. Изначально я выбрал Utility Class, используя большую часть подхода Singleton design pattern при разработке этого пакета Dart. Другими словами, класс состоял из ряда общедоступных статических свойств и общедоступных статических функций, к которым затем можно получить доступ в масштабе всего приложения, просто используя имя класса в качестве префикса "Реклама". очень характерно, есть только один его экземпляр, так как он не предназначен для создания. Однако такой класс не лишен определенных соображений. Те, которые необходимо было решить в отношении цели этого конкретного класса. Он должен был использовать плагин Google с рекламой Admob. Реклама одиночного мобильного приложения.

Большая картина

В этой статье речь идет не столько о самом пакете Dart. Об этом говорилось в предыдущей статье Реклама в вашем приложении в мгновение ока! В этой статье будет объяснено, почему отказ от подхода служебных классов к созданию экземпляров обычного класса с использованием классического конструктора классов. Я объясню первоначальное намерение, а затем объясню, почему я считаю, что последнее воплощение пакета Dart больше подходит для использования в качестве универсальной служебной программы. Тот, который предоставляет, в данном случае, плагин Google для отображения рекламы Admob в любом приложении Flutter, о котором вы только можете мечтать - большом или маленьком. Судя по всему, он будет похож на любой стандартный класс, но есть нюанс. Читайте дальше и узнайте, что.

Больше никакой статики!

В рамках переписывания я удалил большинство статических членов класса. Как видно на скриншоте выше, сравнивая две ветки Github, большая часть исходного пакета Dart сохраняется, но ключевое слово static было массово удалено. В этой статье я объясню, почему и что, на мой взгляд, было лучшей альтернативой именно этому пакету Dart.

Скриншоты! Не Гисты!

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

Давай начнем.

Получить некоторый класс

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

Все еще в одиночестве?

В последние годы было много споров о преимуществах шаблона Singleton. Просто зайдите на сайт overstackflow и убедитесь в этом сами. Основное внимание при использовании шаблона Singleton - это потребность в ресурсах и доступность инфраструктуры. Если рассматриваемый код предъявляет высокие требования к ресурсам (например, к памяти), но его доступ можно регулировать, и к нему нужно обращаться только с перерывами в течение жизненного цикла приложения - шаблон синглтона может быть средством управления такой тяжелой и сложной задачей. требующий немного кода. В конце концов, с помощью этого шаблона когда-либо создается только один экземпляр этого фрагмента кода.

Итак, конечно, если бы я не собирался делиться этой конкретной библиотекой рекламы с кем-либо, являющимся в некотором роде «тяжелым» ресурсом, когда дело доходит до плагина Google, и если бы я собирался использовать его только в начале своего приложения где я, вероятно, инициализирую его, установлю свои прослушиватели событий и покажу свою рекламу - шаблон Singleton был бы «изящным» подходом. В конце концов, у меня было бы дополнительное преимущество - доступ к объявлениям в масштабе приложения с его глобальными свойствами и глобальными методами. Например, я мог бы легко реализовать прослушиватели событий или даже закрывать и открывать рекламу в любое время и в любом месте, где я хотел. Если бы я был единственным, кто его использовал, это было бы относительно безопасно и легко управлять. Однако не только я им пользуюсь. Не больше.

Нет Кодекса - это остров

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

Если бы я настаивал на сохранении шаблона Singleton, поскольку пакет Dart в настоящее время работает, любой и каждый в вашей команде разработчиков сможет добавлять прослушиватели событий в любое время и в любом месте вашего приложения Flutter. Это было бы нехорошо. Вам нужно немного контролировать, кто и что может делать с вашей рекламой. В конце концов, цель всего этого - заработать на этой рекламе немного денег. Кто знает, что бы эти разработчики сделали, чтобы добавить слушателей событий повсюду - без вашего ведома. Другими словами, нужно было бы посвятить кучу нового кода, чтобы просто «контролировать», кто и как будет получать доступ к вашим объявлениям. Было бы много работы. Слишком много работы. Давай не будем этого делать.

Вернуться к основам

Короче говоря, быстрый и простой способ «управлять» тем, у кого есть доступ к вашим объявлениям, - это контролировать доступ к тому самому классному объекту, который управляет вашими объявлениями. В этом случае ими будет управлять один-единственный объект класса. Я вскоре объясню это последнее утверждение. Затем вы можете управлять доступом к этому одному объекту. Возьми?

Однако вначале, когда я был единственным, кто использовал его, у меня был полный доступ к методам класса Ads и его свойствам! У меня был доступ ко всему с помощью геттеров. У меня был доступ даже к идентификатору приложения Admob и всем идентификаторам модулей Admob! Почему? Почему нет! Я подумал, что, возможно, захочу использовать их где-нибудь еще в своем приложении. Я не знал. Мне было все равно. Это была моя собственная небольшая библиотека рекламы, и я использовал подход синглтона: «Мир был моей Oyster!»

В последней версии его количество сократилось до пяти геттеров. Как видно на скриншоте выше, в столбце справа теперь используется старый добрый конструктор класса. Это больше не список статических ссылок. Что еще ты видишь? Видите ли, если вы хотите выполнить конкретный получатель, вам понадобится доступ к определенному объекту. Такой подход позволяет легко контролировать. Вы можете контролировать, кто имеет доступ к этому конкретному объекту. Даже если экземпляр класса Ads создается снова в другом месте! Подробнее об этом чуть позже.

На данный момент все, что вам нужно знать, это то, что никому не нужно знать ваш идентификатор приложения Admob, идентификатор вашего подразделения или даже иметь доступ к объектам рекламы, которые создаются в классе Ads. Вам нужно только знать, что вы, скорее всего, первым используете их для создания объекта Ads, и, как оказалось, это ключ к изменениям, внесенным в эту версию класса Ads.

Ясно как подливка.

Итак, однажды, когда я один использовал класс Ads, я с радостью разработал очистительные функции, которые одним махом очищали определенный тип от прослушивателей событий! Однако предоставление такой возможности широкой публике - не лучшая идея. Вы сможете очистить прослушиватели событий других людей! Нехорошо. С помощью этого плагина вы можете добавлять прослушиватели событий к своим объявлениям. Пакет Dart дает вам средства для этого, и он более подробно описан в предыдущей статье Добавьте рекламу в свое приложение в мгновение ока! Однако это означает, что только вы должны иметь право удалять их, и только они.

На скриншоте, сравнивающем две ветви, вы видите, что функция dispose () класса Ads немного изменилась, но с большими последствиями. Ушли семь публичных функций. Теперь у вас должен быть доступ к объекту Ads, чтобы "удалить" его должным образом. Если вы хотите очистить прослушиватели событий, они должны быть в первую очередь вашими прослушивателями событий.

Удалено самим

Итак, как удалить объект обработчика событий? Взглянув на него по самому его объекту и удалив его. Вот как. Обратите внимание: нечасто бывает нужно удалить обработчик событий во время работы приложения. В большинстве случаев вы бы «установили и забыли». Он будет очищен при закрытии приложения (с помощью функции dispose ()). В любом случае, если вам нужно, у вас есть такая возможность. Посмотрите внимательно на скриншот ниже.

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

Обратите внимание, что «ads.screen» и «ads.video» имеют те же функции, что и «ads.banner», поэтому я не стал их указывать. Я перечисляю только уникальные функции. Все эти функции возвращают логическое значение. Если переданный объект функции, подлежащий удалению, найден, он удаляется и возвращается логическое значение true. Если обработчик событий не найден, возвращается false. Нет никаких других жалоб, кроме этой. Приложение не выйдет из строя, если обработчик событий не найден. Он просто давит - как и положено хорошей служебной программе. У вас должен быть доступ к вашим собственным обработчикам событий, поэтому вы сможете их успешно удалить. В любом случае, именно так, когда вы имеете доступ только к своим обработчикам событий, а не к тем, которые принадлежат другим лицам. Есть немного встроенной устойчивости.

Что изменилось?

Итак, вы видите, что в примере кода теперь создается экземпляр объекта класса Ads. Идея в том, что теперь вам решать, как и кто имеет доступ к этому объекту. Вы можете, например, превратить его в InheritedWidget. Вы можете определить переменную ads как статическую переменную, возвращающую вас к исходной точке… если хотите. Что бы вы ни придумывали, все зависит от вас. Сам объект самодостаточен.

Установите это и забудьте

Ну вот и все. Теперь у вас есть пакет Dart, который отображает для вас рекламу. Позвольте мне предложить вам создать экземпляр класса Ads и, таким образом, инициализировать плагин где-нибудь в начале вашего приложения. Укажите идентификаторы, укажите соответствующие параметры, определите слушателей событий, и вы в пути. Когда приложение закрывается, у вас будет функция dispose () в собственной функции dispose () соответствующего объекта State для выполнения очистки. Ниже приведены три примера, в которых вы передаете идентификатор блока для рекламного баннера. Первые два требуют, чтобы функция "show" вызывалась позже. В то время как последний пример определяет, а затем показывает рекламный баннер за один вызов функции. Отлично.

Обратите внимание, как все это делается в одном месте. Вы можете регулировать, кто из ваших разработчиков будет иметь доступ к этому фрагменту кода. В качестве альтернативы вашим соотечественникам не обязательно иметь доступ к этому фрагменту кода и, следовательно, не иметь доступа к этим идентификаторам (appId, bannerId, и т. Д. ). Опять же, вы можете регулировать доступ, контролируя, кто будет иметь доступ к объекту, рекламе.

Рассмотрим некоторые предположения

Именно здесь вам следует принять во внимание некоторые предположения, сделанные при использовании плагина firebase_admob:

  • Один плагин на приложение.
  • Максимум один идентификатор единицы для каждого "типа" объявления (баннер, межстраничное объявление и видео).

Плагин не позволяет использовать в приложении более одного идентификатора приложения. По крайней мере, такое впечатление у меня складывается из документации. Вы не можете разрешить показ рекламы в одной части приложения, а ваш приятель - в другой. Все они должны быть под одним «идентификатором приложения». Это хорошо с точки зрения управления классом Ads. Это позволило мне реализовать средства для решения вопроса о том, что можно просто создать экземпляр другого объекта класса Ads.

Как насчет другого?

Я имею в виду, что мешает кому-либо просто создать еще один экземпляр класса Ads? Ничто их не останавливает. Как служебная программа, она не должна их останавливать. Такие программы должны «плыть по течению» в повседневной работе мобильного приложения. Любое мобильное приложение - чем бы оно ни занималось! Таким образом, мобильное приложение может создать второй объект Ads. Опять же, по самому своему определению обычный конструктор класса позволит вам это сделать. Он может создавать любое количество рекламных объектов. Итак, давайте посмотрим, что произойдет, когда мы создадим еще один объект Ads.

Должен быть только один!

Допустим, в процессе разработки вы решили войти в свою любимую среду IDE и набрать фрагмент кода, который вы видите выше. Вы собираетесь создать не один, а два объекта Ads. Один за другим. Затем вы запускаете его в «режиме отладки». Посмотрите, что происходит ниже. Вам представлен "экран смерти"!

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

Флаг инициализации

Десятки статических ключевых слов были удалены в этой версии класса Ads. Однако была вставлена ​​одна статическая переменная (одно свойство класса). Это логическая переменная, _ инициализированная. Помните первое предположение: «Один плагин на приложение». Что ж, это средство для реализации этого предположения при использовании этого пакета Dart. Эта переменная свойства и другая логическая переменная экземпляра, _firstObject, предоставят вам контроль над подключаемым модулем Google, который мы в настоящее время используем для наших объявлений. Они гарантируют, что плагин инициализируется только один раз, как он был разработан. Вы можете увидеть обе эти переменные, определенные на скриншоте ниже. Один изначально установлен в значение true; другой изначально установлен на false. Одна переменная экземпляра; другая - статическая переменная, видимая для всех экземпляров этого класса.

Адаптивный код

Ниже небольшими красными стрелками выделена логика, которая запускается при создании экземпляра класса Ads в объекте. Код предназначен для запуска в производственной среде, даже если значение null по какой-то причине передается в «идентификатор приложения», и для запуска в производственной среде, даже если экземпляр класса Ads создается десятки раз.

Такие кейсы не «взорвут» приложение. Вместо этого класс Ads просто не будет отображать рекламу. Или, если он отображает рекламу, это будут тестовые объявления. В любом случае, только таким образом разработчик будет предупрежден о возможной проблеме - а не рассерженный пользователь, у которого происходит сбой приложения. Показывать рекламу приятно, но она не мешает основной функции мобильного приложения. Что бы это ни было.

Первая красная стрелка показывает, что произойдет, если переданное значение appId будет нулевым или пустой строкой. Не взрывается. Он не уведомляет разработчика (во всяком случае, напрямую). Вместо этого он использует «идентификатор тестового приложения», предоставленный плагином.

Вторая красная стрелка подчеркивает тот факт, что для переменной экземпляра _firstObject установлено значение false, если для переменной класса _initialized уже установлено значение true. Следствием является то, что объект все еще создается. Он просто ничего не делает. Вы увидите это позже.

Обратите внимание на оставшийся фрагмент кода. Если он не «инициализирован» (т. Е. _initialized имеет значение false), для этой (статической) переменной класса немедленно устанавливается значение true, а затем предпринимается попытка инициализировать плагин. Наконец, есть функция then для определения логического результата асинхронной операции, задействованной при инициализации подключаемого модуля. Этот результат присваивается переменной класса _initialized. Посмотрите, как это работает?

Приложение должно продолжаться!

Идея состоит в том, что независимо от того, какой «мусор» может быть передан конструктору, экземпляр класса Ads должен быть успешно создан. В самом коде плагина ниже видно, что appId является обязательным, а если параметр analyticsEnabled не передан, для него установлено значение false. Глядя на последние несколько стрелок выше, вы можете увидеть, что пакет Dart обеспечивает предоставление appId (даже если это «тестовый» идентификатор), а параметру передается логическое значение. analyticsEnabled с помощью оператора ??. Создается экземпляр объекта Ads. Если получится - другое дело.

Первая инстанция побеждает

Теперь, как сделать так, чтобы объект класса ничего не делал? Что ж, в этом случае вы проверяете, не первая ли она. Вот как. Давайте посмотрим на функцию showBannerAd (). В нем есть две новые строчки по сравнению с последней версией этого класса. Они отмечены стрелками внизу. Вы узнаете задействованную переменную.

Вы можете создать свой второй объект Ads, но если вы вызовете, например, его функцию showBannerAd (), вас ждет небольшое разочарование. Если вы делаете это в своей среде IDE в «режиме отладки», вы получите «красный экран смерти». Если вы запускаете его в производственной среде со вторым объектом Ads, созданным в какой-либо части приложения, не находящейся под вашим управление например, просто не получится. Благодаря строчке if (!_firstObject) return;

Вы обнаружите, что каждая общедоступная функция в этом классе Ads теперь имеет строку для «отключения» объектов Ads, которые были созданы, хотя, откровенно говоря, они не должны были иметь. По замыслу, может быть только один. Первый. И по замыслу ваш должен быть первым. В конце концов, это ваше приложение. Посмотрите, как это работает сейчас? И если он не первый, вы это узнаете! Ваш не пойдет! Или будут тестовые объявления.

Скриншоты трех общедоступных функций показывают, что каждая из них теперь имеет операторы assert и if в начале своего кода. Это верно для всех общедоступных функций, используемых в этом классе. Если не первый, то скучный. Это мало что даст. Первый объект Ads предназначен для работы с рекламой в вашем приложении. Никакого другого. Сам класс Ads гарантирует, что это.

Единое решение

Теперь, если вам действительно нравится и нужен подход Singleton, который вам легко доступен. Просто сделай один. С помощью языков ООП, таких как Dart, вы можете составить класс, который использует этот пакет Dart именно таким образом. После этого у вас будет ссылка и доступ к этому единственному экземпляру во всем приложении.

Ну вот. Я придумал пример такого подхода. Вы можете заполнить остальные функции в той степени, в которой вам нужно. Я, например, предоставил только возможность showBanner, но вы можете сделать все остальное. Однако у вас есть доступ ко всей его обработке событий. Разве программирование не замечательно?

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

Посмотрите на функцию init (). Видите оператор ?? =? Он назначается только в том случае, если переменная имеет значение NULL, и поэтому позволяет только «первый» вызов функции init () для однократного создания экземпляра этого класса. Если какой-нибудь чрезмерно усердный разработчик снова и снова вызывает функцию init (), это не причинит вреда. Ниже представлен фрагмент кода примера, который теперь вызывает статические функции, находящиеся в этом служебном классе, AppAds.

Знай, что есть неизвестное

Найдите время, чтобы изучить код. Посмотрите на излишки здесь и там. Вы когда-нибудь видели в своей жизни так много операторов if, проверяющих значение null? Обратите внимание, где используется оператор ??. Это все потому, что значения параметров поступают из внешнего мира, и поскольку этот пакет Dart должен использоваться в любом приложении, я понятия не имею, что там есть. Все, что я знаю, это пакет Dart для показа вашей рекламы. Если он не может показывать вашу рекламу, он будет показывать тестовые объявления. Если он не может отображать тестовые объявления, он вообще ничего не сделает. Вам решать, почему. По крайней мере, это не приведет к сбою вашего приложения, и это цель. Если он должен потерпеть неудачу, терпите неудачу изящно и тихо.

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

По ошибке или нет

Прямо сейчас, когда дело доходит до обработчиков событий, представленных в плагине, обработка ошибок лежит на вас. Поскольку это код разработчика в обработчиках событий, идея состоит в том, что сам пакет Dart оставит его разработчику, чтобы гарантировать, что код будет обрабатывать любые исключения. Считается, что размещение некоторой обработки ошибок, позволяющей, например, срабатывать оставшимся прослушивателям событий, является слишком «защитным» кодом. Пусть вместо этого приложение взорвется! Очевидно, что есть проблема с кодом разработчиков, поэтому им нужно узнать об этом как можно скорее с помощью небольшого красного экрана.

Возможно, однако, небольшое изменение в пакете Dart и структуры try..catch могут быть реализованы (см. Ниже), чтобы обязательно записывать любые исключения, которые могут произойти, и разрешить общую операцию обработки событий для Продолжить. Опять же, кто знает, что происходит во внешнем мире. При определенных обстоятельствах, может быть, лучше обработать любые исключения и, возможно, установить флаг «ошибка», чтобы уведомить приложение, но, тем не менее, продолжить и запустить следующий обработчик событий в очереди. В любом случае не допускайте сбоев приложения! Дайте мне знать, что вы думаете, в комментариях ниже.

К ошибке! Нет!

Поймать рекламную ошибку

Итак, я выбрал пакет Ads Dart, чтобы пойти по менее навязчивому пути. Если код в вашем обработчике событий выйдет из строя, это не приведет к сбою приложения ... если вы явно этого не захотите. Например, разработчик может использовать оператор assert со свойством inError для обнаружения любых ошибок во время разработки. При желании все ошибки, связанные с обработчиками событий, могут быть устранены. Смотрите ниже на скриншоте, изображающем пример кода. Исключения и тип события записываются в объекте List eventErrors.

В конце концов

Как автор таких служебных программ, вы не можете предвидеть возможные причины, по которым значения NULL передаются, например, в качестве параметров. Все, что вы могли сделать, это проверить нулевые параметры и адаптироваться к таким экземплярам. Разрабатывая такие программы, вы постоянно спрашиваете себя: «А что, если это произойдет?» И «А что, если это произойдет?», И пишете свой код соответствующим образом. Однако вы должны достичь баланса. Слишком много «защитного» кода так же плохо, как и слишком мало.

Опять же, этот пакет Dart предназначен для показа рекламы. Есть надежда, что вы будете использовать его для этого в своем собственном приложении. Я не знаю, какое у вас приложение. Я не знаю, насколько сложно, насколько просто, насколько велико или насколько мало. Я не знаю, и мне все равно. «The World’s your Oyster!» Все, что я знаю, это мой пакет Dart, который позволит вам запускать ваше приложение - с рекламой.

Ваше здоровье.

# Исходный код по состоянию на 4 июля 2019 г.
* Исходный код по состоянию на 27 июня 2019 г.
^ Исходный код по состоянию на 30 мая 2019 г.

→ Другие рассказы Грега Перри