Передача данных между представлениями и моделями в среде Flex MVC
Я никогда раньше не использовал Flex/Actionscript, поэтому извините, если я спрашиваю что-нибудь очевидное, но я работал над этим в течение 3 дней (включая поиск в Google и stackru) перед написанием этого поста.
Меня попросили изменить игру, написанную на Flex 4, с использованием MVC-инфраструктуры на основе mini-IoC. Меня попросили сделать два мода - это игра поверх экрана, которая отображает итоговый счет и выбор сложности на вводном экране. Я сделал игру поверх экрана, и мне удалось заставить контроллер вызвать ее, когда таймер игры заканчивается.
Итак, пока структура игры выглядит так:
Intro View -> Game View -> Game Over View
^ |
|__________ (retry?) ________|
Первая проблема состоит в том, чтобы передать результат из файла ActionScript mainGame в экран игры.
Вещи, которые я пробовал:
- Импортируем mainGame в gameOverViewBase и вызываем переменную mainGame.score в файле gameOverView mxml.
-РЕДАКТИРОВАТЬ!!! = вышеупомянутый метод работает, если я изменяю переменную счета в mainGame на константу, но если она остается переменной, контроллер не загрузит gameOverView, и игра окажется в пустом представлении mainGame.
- Создание функции, которая добавляет новую переменную счета в gameOverViewBase всякий раз, когда игрок набирает очки во время игры.
- Передача партитуры в качестве параметра в GameOverView по окончании MainGame
controller.loadGameOver(score);
Это казалось наиболее логичным способом сделать это. Поэтому я следил за функцией через другие компоненты игры, устанавливая loadGameOver, чтобы принимать целое число в качестве параметра, пока не попал в основной файл ActionScript игры:
public function loadGameOver(score:int) : void
{
loadView(GameOverView);
}
Функция loadView (показанная ниже) - это то место, где я застреваю, потому что не вижу, где передать параметр "оценка". Это выглядит так:
private function loadView(viewClass:Class, modelClass:Class = null) : void
{
var view:View = new viewClass();
if(!view) throw new Error("Could not load view");
viewContainer.removeAllElements();
viewContainer.addElement(view);
view.controller = this;
}
Вторая проблема - выбор сложности на экране ввода. Я сделал это с 3 кнопками (легко, нормально, сложно) в файле mxml и для каждой кнопки в ActionScript:
protected function onEasyButtonClick() : void
{
set = "easy"
controller.loadMainGame(set);
}
Еще раз, я заканчиваю в вышеупомянутой функции loadView.
Подводя итог: мне нужно знать, как передавать данные между представлениями и моделями. Если это не идеальный метод, я открыт для любых других методов, которые вы считаете лучше.
Благодарю вас!
Бен
PS Я могу отправить свой исходный код любому, кто хотел бы помочь:)
1 ответ
Вы не указываете, какую платформу MVC вы используете, что было бы полезно. Тем не менее, оценка должна определенно быть свойством модели, и данные модели должны быть доступны для представления либо напрямую, возможно, через связывание (спасибо weltraumpirat), либо через некоторый промежуточный класс.
Я бы посоветовал вам взглянуть на некоторые из существующих классов представлений и попытаться выяснить, как они подают данные модели. Вы можете использовать этот подход, чтобы получить данные, необходимые для вашего просмотра.
[РЕДАКТИРОВАТЬ]:
mainGame
собственность не устанавливается на ваш GameOverView
экземпляр, так что вы не можете получить доступ к его score
свойство либо через связывание или через след. loadView
Метод вашего класса контроллера принимает Model
ссылка на класс, который он использует для создания нового Model
экземпляр будет использоваться новым View
, К сожалению это бесполезно для вас, как вашего GameOverView
нужен экземпляр MainGame
который был создан для MainGameView
(и который содержит текущий счет).
Я не знаю, вписывается ли следующее в философию используемой вами платформы. Тем не менее, я бы изменил loadView
способ принять экземпляр Model
а не ссылка на класс, и создать и кэшировать ссылку на экземпляр MainGame
когда ваш контроллер создан. Таким образом, вы можете пройти то же самое Model
ссылка как на MainGameView
а также GameOverView
когда они созданы.
public class WhackAMoleBase extends Application implements IGameController
{
public var viewContainer:Group;
private var mainGame:MainGame
public function WhackAMoleBase() : void
{
super();
// Create and cache an instance of the main game Model
mainGame = new MainGame();
addEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete);
}
public function loadIntroduction() : void
{
loadView(IntroductionView);
}
public function loadMainGame() : void
{
loadView(MainGameView, mainGame);
}
public function loadGameOver() : void
{
// Use the same instance of MainGame which the MainGameView
// has been using as the Model for the GameOverView
loadView(GameOverView, mainGame);
}
// Accept a Model instance rather than a class Reference
private function loadView(viewClass:Class, model:Model = null) : void
{
//Create a new instance of the supplied view
var view:View = new viewClass();
if(!view) throw new Error("Could not load view");
//Clear any previous views in the container and add
viewContainer.removeAllElements();
viewContainer.addElement(view);
//Property based dependency injection
view.controller = this;
//There may or may not be a model required for the
//requested view; check and instantiate appropriately
if(model)
{
//Give model reference to the controller
//and link the view up to the model
model.controller = this;
view.model = model;
}
}
private function onCreationComplete(event:FlexEvent) : void
{
//When the application is first created, we want to show the introductory view
loadView(IntroductionView);
}
}