Объектные модели Android

#android

#Android

Вопрос:

Я проработал в области разработки программного обеспечения несколько лет (более 10) и только начинаю по-настоящему разбираться в Android. Насколько я понимаю, графический интерфейс состоит из действий (замена форм и т.д.), И Каждое из них обрабатывается почти как отдельная мини-программа, поскольку передача ссылок на данные — не самый простой подход, а те, которые доступны, не особенно приятны.

В любом случае, мой текущий предпочтительный подход к разработке GUI заключается в создании объектной модели, которая содержит все функции, которые я хочу предоставить, а затем я могу создать GUI (или консоль, или доступ к серверу, или что угодно) для взаимодействия с этой моделью через интерфейсы. Отдельным формам могут передаваться урезанные интерфейсы и только частичные части модели, которые используются для этой конкретной формы. Для меня это отделяет интерфейс от функциональности, а также абстрагирует реализацию объектной модели от графического интерфейса. Одним из преимуществ для меня является то, что я могу написать библиотеку для выполнения чего-либо, а затем использовать графический интерфейс Java, Android GUI, консоль, что угодно. На самом деле, я иногда разрабатываю функциональность до разработки любого графического интерфейса.

Теперь, в Android, это, по-видимому, более сложный подход. Я думаю, что мог бы достичь того же, сериализовав модель и ее части и передавая их в виде строк, но я не уверен, что это практично. Я также вижу, что это не сработало бы, если бы части модели потребовался обратный вызов к другой части модели, которая не будет существовать, потому что ее не было в разделе serialized. т.е. у меня есть объектная модель, которая содержит список объектов данных. Я хочу передать объект данных в другое действие, и если он вообще будет отредактирован, перезвоните к объектной модели, чтобы она могла делать что-то еще.

Могу ли я написать что-то для повторного использования моих объектных моделей или этот подход просто плохо работает с Android? Если это действительно работает, то как? Если нет, то какие подходящие альтернативы я могу использовать?

Комментарии:

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

2. Да, я видел это, но это был один из моих «не особенно приятных» вариантов. Я не в восторге от наличия глобальных значений. Весь подход, который я использую, заключается в разделении, а затем я использую globals для Android, просто мне это не нравится. Очевидно, что если это единственный подход, то у меня может не быть выбора.

3. Ну, можно передавать объекты между действиями, используя полное имя класса объекта в качестве пары имя / значение. Это не на 100% типобезопасно, но выполнимо.

4. Однако это не ссылка на объект. Это сериализованный клон объекта, не так ли?

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

Ответ №1:

Вы пытаетесь смоделировать разработку Android с помощью графического интерфейса рабочего стола или консольного режима разработки.

Скорее, рассмотрим веб-разработку.

Если вы не воспользовались node.js преимуществом, ваше веб-приложение написано не на Javascript. Тем не менее, многие функции вашего графического интерфейса будут реализованы на Javascript (например, проверка на стороне клиента, принудительное заполнение обязательных полей перед включением кнопки отправки). Хотя у вас может быть расширенная объектная модель для обработки большей части вашей бизнес-логики, она будет находиться на сервере, на Java, Ruby, PHP, Perl, Python или любом другом. Веб-страницы напрямую не взаимодействуют с этой расширенной объектной моделью. И каждая веб-страница стоит отдельно, передавая данные на другие страницы только относительно ограниченными данными в парах ключ-значение ( GET параметры).

Android с точки зрения архитектуры представляет собой смесь шаблонов настольной и веб-разработки. Действия являются автономными объектами, слабо связанными, как и веб-страницы. Вы не передаете объекты модели между действиями, точно так же, как вы не передаете объекты модели между веб-страницами.

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

Будет ли это центральное хранилище опосредовано Service или через какой-либо синглтон, зависит от вас и будет зависеть от того, что на самом деле должна была представлять эта богатая объектная модель.

Комментарии:

1. хорошо, я могу вроде как понять, как это могло бы работать. Я мог бы продолжать использовать свой объект как статический на уровне приложения, но выполнять действия с использованием более общего интерфейса для получения из него данных (например, GET), а не с использованием вызовов, которые я предоставляю. Я могу передать намерение ПОЛУЧИТЬ эти данные в Activity, и оно может использовать приложение, чтобы найти их и поработать над ними. Я думаю, что это мог бы быть работоспособный подход. В качестве примера, скажем, откройте действие с чем-то вроде «ПОЛУЧИТЬ данные учетной записи для Кевина», и тогда приложение будет иметь «Функцию получения сведений об учетной записи», которую вызывает подактивность с Кевином в качестве аргумента.

2. кстати, я думаю, вы правы в том, что то, как я смотрю и как я это выразил, предназначалось для разработки на настольных компьютерах, но на самом деле это не было моим намерением. Мое реальное намерение — отделить бизнес-логику от интерфейса, и я просто не рассматривал подход в веб-стиле. Фактически я могу сохранить свою библиотечную модель и обернуть ее некоторым кодом извлечения для работы с Android.

3. @Matt_JD: «Фактически я могу сохранить свою библиотечную модель и обернуть ее некоторым кодом извлечения для работы с Android» — да. Самая большая разница, которую я вижу, заключается в том, что вы передаете ключи в центральную (возможно, статическую) коллекцию по сравнению с передачей самих объектов.

4. Должен сказать, что я тот, кто любит уменьшать связь (возможно, немного чересчур) Мне действительно понравилась идея подхода Android, но я чувствовал, что практически это ограничивает. Я нашел ваш ответ поучительным, и моя вера в подход несколько улучшилась. Я думаю, что это было бы улучшено еще больше, если бы существовал способ зафиксировать намерение создать действие и предоставить ему интерфейс, в котором он может найти функцию «GET». Указанный вами подход, похоже, связывает Activity с приложением, поэтому его нельзя повторно использовать. Хотя я мог бы не обращать на это внимания.

5. кстати, я не игнорирую принятие вашего ответа. Я просто даю другим людям шанс и себе самому попробовать это первым. 🙂

Ответ №2:

Мэтт… Я понятия не имею, почему ваш вопрос заставил меня задуматься. Итак, вот какой-то безумный код:

Учитывая интерфейс:

 public interface ISayHello {
    public void SayHello();
}
  

Конкретный класс sayHello

 public class SayHello implements ISayHello, Serializable {
    public void SayHello() {
        Log.d(Main.TAG,"hello");
    }
}
  

Можно передать полное имя интерфейса в intent как:

                 Bundle b = new Bundle();
                SayHello say= new SayHello();
                b.putSerializable("qprinstitute.crisis.ISayHello", say);
                intent.putExtras(b);
                startActivity(intent);
  

И приведите экземпляр конкретного класса к типу (интерфейсу) в принимающем действии как:

 Intent i= getIntent();
if (i != null) {inBundle= i.getExtras();}
if (inBundle != null) {
    ISayHello say= (ISayHello)inBundle.getSerializable("qprinstitute.crisis.ISayHello");
    say.SayHello();
}
  

Который регистрирует «привет». Круто!

Комментарии:

1. Привет, я думаю, это просто зависит от того, как работают интерфейсы и сериализация. На самом деле это не решает мою проблему. Это работает, потому что журнал статичен и поэтому не будет привязан к экземпляру sayHello. ISayHello, который десериализуется действием, не является тем же объектом, что и исходный, который создается; это клон. Я думаю, что если бы вы могли сделать так, чтобы исходный sayHello открывал порт или использовал обратный вызов, и всякий раз, когда вызывался sayHello, он передавал бы данные в порт или обратный вызов, вы бы увидели, что это не сработает. Клон был бы перестроен, но не ссылался бы на те же объекты.

2. @Matt_JD … У вас это может не сработать. Я просто представлял, скажем, набор записей getData(); где getData() инкапсулирует идентификатор пользователя, базу паролей и хранимую процедуру.

3. Да, объединенный тип данных. Однако здесь я больше ищу сохранение функциональности и разрешение обратных вызовов. Я думаю, что подход Commonsware подходит лучше всего, и я могу придумать несколько настроек, которые, возможно, сделали бы его более таким, как мне нравится. Возможно, я сыграю и опубликую свой ответ на основе его, когда у меня будет время.