Измените <view
на <View
, потому что view
не находится в пустом представлении. Это для пользовательского представления, определенного через class
attr, как показано ниже:
<view
android:layout_width="wrap_content"
android:layout_height="wrap_content"
class="com.your.package.YourCustomView" />
И вы получили
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
из-за LayoutInflater
пытается разобрать class
attr:
LayoutInflater
Исходный код
//...
View createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
boolean ignoreThemeAttr) {
if (name.equals("view")) { // line 724
name = attrs.getAttributeValue(null, "class"); // line 725
}
// Apply a theme wrapper, if allowed and one is specified.
if (!ignoreThemeAttr) {
final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);
final int themeResId = ta.getResourceId(0, 0);
if (themeResId != 0) {
context = new ContextThemeWrapper(context, themeResId);
}
ta.recycle();
}
if (name.equals(TAG_1995)) { // line 738
// Let's party like it's 1995!
return new BlinkLayout(context, attrs);
}
//...
view
и получает true
class
attr и получает null
blink
и получает сбой Кроме того, есть любопытная вещь, разработчики Android добавили пасхальное яйцо, вы можете попробовать:
<view
android:layout_width="wrap_content"
android:layout_height="wrap_content"
class="blink">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Some text" />
</view>
Переключатель подобен любой другой структуре управления. Есть места, где это лучшее / чистое решение, и многие другие места, где это совершенно неуместно.
В дизайне OO обычно считается предпочтительным в такой ситуации, как ваша, использовать разные типы сообщений / классы, которые наследуются от общего класса сообщений, а затем использовать перегруженные методы для «автоматически» различают разные типы.
В случае, подобном вашему, вы можете использовать перечисление, которое сопоставляется с вашими кодами действий, а затем присоединить атрибут к каждому перечисляемому значению, которое позволит вам использовать дженерики или тип -building для создания разных объектов подкласса Action, так что будет работать метод перегрузки.
Но это настоящая боль.
Оцените, есть ли опция дизайна, такая как перечисление, которое возможно в вашем решении. Если нет, просто используйте переключатель.
Я не покупаю его. Кажется, что у этих фанатиков ООП есть машины, у которых есть бесконечная оперативная память и потрясающая производительность. Очевидно, что при использовании inifinite RAM вам не нужно беспокоиться о фрагментации ОЗУ и о влиянии производительности, которое возникает при непрерывном создании и уничтожении небольших вспомогательных классов. Перефразируя цитату из книги «Красивый код» - «Каждая проблема в информатике может быть решена с еще одним уровнем абстракции»
Используйте переключатель, если вам это нужно. Компиляторы довольно хороши для генерации кода для них.
Я помещал сообщения в массив, а затем сопоставлял элемент с ключом решения, чтобы отобразить сообщение.
На ум приходит Strategy
.
Шаблон стратегии предназначен для предоставления средства для определения семейства алгоритмов, инкапсулирования каждого из них в качестве объект и сделать их взаимозаменяемыми.
blockquote>В этом случае «семейство алгоритмов» - это ваши разные действия.
Что касается операторов switch - в «Чистом коде» Роберт Мартин говорит, что он пытается ограничить себя одним оператором switch для каждого типа. Не исключать их вообще.
Причина в том, что операторы switch не придерживаются OCP .
С точки зрения дизайна вы можете использовать Command Pattern для данного сценария. (См. http://en.wikipedia.org/wiki/Command_pattern ).
Если вы неоднократно повторяете использование операторов switch в парадигме ООП, это свидетельствует о том, что ваши классы могут быть плохо оформлены. Предположим, что у вас есть надлежащий дизайн супер и подклассов и много полиморфизма. Логика операторов switch должна обрабатываться подклассами.
Для получения дополнительной информации о том, как вы удаляете эти инструкции switch и вводите соответствующие подклассы, я рекомендую вам прочитать первую главу «Рефакторинг» Мартином Фаулер. Или вы можете найти похожие слайды здесь http://www1.informatik.uni-wuerzburg.de/database/courses/pi2_ss03_dir/RefactoringExampleSlides.pdf . (Слайд 44)
Операторы «Bad» switch часто включают тип объекта (или что-то, что может быть типом объекта в другом проекте). Другими словами, жестко кодировать то, что может быть лучше обработано полиморфизмом. Другие типы операторов switch могут быть в порядке
Вам понадобится оператор switch, но только один. Когда вы получите сообщение, вызовите объект Factory для возврата объекта соответствующего подкласса Message (Move, Attack и т. Д.), Затем вызовите метод message-> doit () для выполнения работы.
означает, что если вы добавляете больше типов сообщений, необходимо изменить только заводский объект.
Map<Class<?>, Thing>
, это очень похоже на «выполнение переключателя на классах», но это, однако, принято как хорошая практика?
– YoTengoUnLCD
20 June 2016 в 20:14
Использовать команды. Оберните действие в объект и пусть полиморфизм сделает для вас переключатель. В C ++ (shared_ptr
- это просто указатель или ссылка на языке Java. Это позволяет динамическую отправку):
void GameServer::perform_action(shared_ptr<Action> op) {
op->execute();
}
Клиенты выбирают действие для выполнения, и как только они отправляют это действие на сервер, поэтому серверу не нужно выполнять синтаксический анализ:
void BlueClient::play() {
shared_ptr<Action> a;
if( should_move() ) a = new Move(this, NORTHWEST);
else if( should_attack() ) a = new Attack(this, EAST);
else a = Wait(this);
server.perform_action(a);
}
Операторы IMO switch
не являются bad , но их следует избегать, если это возможно. Одним из решений было бы использовать Map
, где ключи являются командами, а значения Command
- объектами с помощью метода execute()
. Или List
, если ваши команды являются числовыми и не имеют пробелов.
Однако, как правило, вы должны использовать switch
заявления при реализации шаблонов проектирования; одним примером может быть использование шаблона цепочки ответственности для обработки команд, заданных любой командой «id» или «value». (Был также отмечен шаблон Strategy .) Однако в вашем случае вы также можете изучить шаблон Command .
В основном, в OOP, вы попытаетесь использовать другие решения, чем полагаться на блоки switch
, которые используют парадигму процедурного программирования. Однако, когда и как использовать это - это ваше решение. Я лично часто использую блоки switch
при использовании шаблона Factory и т. Д.
Определение организации кода:
Collection
API во многих фреймах) Math
... add
метод будет полагаться на другие методы для этого и не будет выполнять эту операцию сам, потому что это не контракт). Поэтому, если ваш оператор switch
выполняет различные операции, вы « нарушает » это определение, тогда как использование шаблона проектирования не соответствует каждой операции в собственном классе (это собственный набор функциональных возможностей).
PlayerAction
enum сpublic static PlayerAction forActionId(int actionId)
, а enum будет иметь общедоступный метод типаdoAction
. Нет необходимости в коммутаторе, простоPlayerAction.forActionId(number).doAction(args);
. Теперь все, что вам нужно сделать, чтобы добавить другое действие, это добавить значение перечисления и реализовать на нем методdoAction
. ПРИМЕЧАНИЕ. Мне не нравится использовать «порядковый номер». либо, так как легко переупорядочить ваши значения перечисления в алфавитном порядке и сломать что угодно, используя старые цифры. – Shadow Man 29 March 2018 в 23:40