首页

源码搜藏网

首页 > 开发教程 > 手机开发 >

如何让你的Android项目更容易移植到的Windows / MacOS的(反之亦

创建时间:2016-05-24 09:10  

使用ThinkAlike,正在进行的Java框架MVVM(采用的Android和JavaFX作为视图层),来实现跨平台的炉石游戏卡的参考和更多。
ThinkAlike的Android ThinkAlike的JavaFX
介绍
本文讨论了使用Java和MVVM模式实现Android的桌面跨平台应用程序的实用性。
 
我想向大家介绍ThinkAlike代码库首先,我已经实现了我的跨平台战略。
 
这是一个持续的Java框架MVVM(采用的Android和JavaFX的(或SWT,Swing的)作为视图层),旨在更容易跨平台开发。
特别是,如果你想继续服用Android原生SDK的充分利用,同时保持跨平台的可能性,这个Java解决方案的工作。
这是不是 单声道/ Xamarin - .NET解决方案是很好的。但在某些情况下,Java解决方案是Android的母语将更预期。
这是不是 PhoneGap的/科尔多瓦 -混合解决方案仍具有UI / UX的缺陷在一定程度上。
这是不是一个生产性的框架,但(进行中)。许多有用的功能,可以添加,如组件级属性绑定(是否可编辑,可关闭,验证规则,热键等)。但是,它已经通过小规模的项目支付,一个跨平台的搭载EPUB阅读器(适用于Android和Windows)来验证其可行性和可扩展性。
一些香料添加到MVVM框架,一些游戏的因素(图像)已经被引入了。 炉边,由暴雪娱乐公司新发布的免费任玩策略卡牌游戏,将用作我的主题。就像本场比赛针对跨平台的市场,我们的目标将是一个卡参考库 Android和桌面平台(屏幕截图如上图所示)。 
 
 
我将举例说明了跨平台的交易流程通过实施如何“ 选择的节点显示详细信息(卡)一步一步”。与MVVM经验的读者可直接进入核心内容。 
必要的介绍相关概念(MVVM,Android的, JavaFX的)包含在背景部分。对于如何建立开发环境,看到环境一节。特别是,对于读者谁怀疑JavaFX应用程序可以被分配到没有安装JRE的平台,请参阅分配部分。
 
背景
跨平台解决方案MVVM引用,经验丰富
 
在设计阶段,我曾提到的iOS WebKit的,ZK,Xamarin,Android的结合,的PhoneGap和JavaFX。在此之前,我已经有在WPF项目经验(MVVM的“母亲”,而MVP是系谱“父亲”)和Android UI的生态系统。这种跨平台的代码库最初开发,以满足客户实际需求 - 而不是大规模的,但快速发展的Android的桌面项目。
 
知识要求:MVVM,Android的,JavaFX的
 
MVVM在WPF MVVM在ThinkAlike
 
“MV-VM”从MVP模式(Martin Fowler的)起源,是后者为实现WPF / Silverlight的微软的专业化。WPF的MVVM的眼光建议,并在上面第一个图所示。 也有比其他WPF MVVM框架:Java的框架ZK,并为HTML5 AngularJS和KnockoutJS。其实不同层的职责划分是正在进行的讨论和探索的课题。
 
你可能注意到在“视图模型”波浪红色下划线(好吧,我承认那是因为已经忘了关闭拼写检查的〜)。这就是所谓“VM”代表。该视图模型层提取“逻辑”的一部分(用例为导向,与平台无关)从视图层,除了“非逻辑”UI / UX代码(大小,颜色等)。UI / UX开发者可以实现不同的视图模块通信一个视图模型,甚至使用不同的GUI技术(WPF,WinForm的等)。
 
上述第二个数字描述了ThinkAlike的MVVM实现。通过对比,WPF,ThinkAlike使用的iProperty / ICommand的事件处理接口视图层和视图模型层之间的粘合剂。用户命令(而不是中间的UI操作)将被解释为,这将在视图中,并派出由视图模型处理ICommand的事件。同时,UI更新反馈将被解释为将从视图模型由视图被解雇和消费的iProperty(更改)事件。
 
注:数据绑定,约翰Gossman(MVVM创建者)说,“有利也有弊。” 最重要的是,我们的跨平台解决方案不具有“跨平台”UI标记文件还没有,这也减少了数据绑定的好处。如何制定出妥协Android的XML UI标记,JavaFX的的FXML UI标记和其他标记语言之间?甲骨文推出开源JavaFX的iOS和Android,可能导致一些突破。
 
“组件模型”在图的右边是指布局/控制(图像/文本/组合框等)。独立于平台的完整的组件库,如果有更多的资源和鼓励,并已完成,将使开发人员能够实例化和通用(独立于平台的)模块控制特定于平台的布局/控制实例(如Xamarin在.NET做)。但是,由于“跨平台”标记文件的困境,宣告布局受益/ UI中的标记文件控件无法享用。
 
有关MVVM的更多详细信息,
 
Android和JavaFX的平台专用视图层的实现仅仅使用。这些谁在这两个领域有经验,可以知道他们在许多方面的不同之处(如细节喜欢如何自动调整图像到其容器)。但是,即使你不与Android / JavaFX的熟悉,你仍然可以通过这篇文章阅读并掌握MVVM跨平台的流程。
 
Android的主题:
 
JavaFX的主题:
 
MVVM
 
概述:模型视图视图模型,@Wikipedia
WPF框架:莲花V2,@code项目
划界讨论:那么到底是什么视图模型?@InfoQ
Android和JavaFX的
 
概述:培训Android开发:入门
API:Android版 的API
样本:API演示(与Android SDK发布)
意图:意图和意图过滤器
查看:活动
意向查看映射:应用清单
GUI ::布局(Java的+ XML标记):布局
GUI ::布局::片段:构建动态UI与片段
JavaFX的合奏
 
概述:JavaFX的文档
API:JavaDoc的JavaFX的2
样本:JavaFX的合奏(演示选项卡+源选项卡)
GUI ::布局(JAVA):正在与布局中的JavaFX
GUI ::布局(标记):介绍FXML
GUI ::风格:JavaFX的CSS参考指南
环境
以下是我的开发工具盘点:
 
基地:月食/ E(FX)clipse 4.2朱诺+ JDK 1.7
我强烈推荐E(FX)clipse提供的JavaFX工具Eclipse集成开发环境,并保持与其他发展稳定的兼容性。 
JDK 1.7采用JavaFX的。Android项目将默认降解为JDK 1.6编译器遵从性水平。
Android SDK中+ ADT插件
的JavaFX SDK(包含在JDK 1.7)+ JavaFX的场景生成器
包装事业部
ThinkAlike是由3个项目中,有后缀_Generic(独立于平台),_jfx(JavaFX的),和_android(为Android)分别 
资产文件,而相比之下,特定于平台的资源文件,将在通用包进行管理。
 
(对于Eclipse用户)某些设置应适用于特定于平台的项目:
 
Android项目
源文件夹:项目属性>构建路径>链接源...,链接ThinkAlike_generic的\ src到ThinkAlike_android \ src_generic。
资产文件夹:使用链接的源文件夹为好。链接ThinkAlike_generic \资产为ThinkAlike_android \资产。
JavaFX项目
源文件夹:项目属性> Java构建路径>项目>添加...,增加了ThinkAlike_generic。如果使用链接的文件夹,电子(FX)clipse会产生一些问题。
资产文件夹:发现com.thinkalike.jfx.assets的Eclipse中,新建>文件夹>高级包文件夹,创建一个链接文件夹ThinkAlike_generic \资产\ ThinkAlike。构建路径>包括将其纳入到构建罐子。
功能设计
完整版本的卡参考图书馆可能有这样的特点:
 
节点(卡)选择器(基本)
节点(卡)的详细信息(基本)
显示所选卡在中心区的详细信息(在卡选择器)。
节点(卡)选择过滤器(基本,TODO)
一叠卡片生成器(TODO)
基于魔法门计算卡组成提示(高级)
卡甲板之间的竞争自动(高级)
No.1-3是通用的功能和将在ThinkAlike项目来实施。甲板生成器可以派生作为未来一个独立的项目。功能2,显示卡的细节,将在本文中加以说明。
 
建筑分析与设计
序列图
 
ThinkAlike MVVM序列图(点击放大) 
(点击放大)
 
详细情况将在以纯文本来说明实施部分。
 
词汇表
 
为了避免歧义,以下术语的使用将予以澄清:
 
特定于平台的:也被称为“平台相关”。指的是链接到一个特定的技术平台,如Android,JavaFX的功能/模式。
平台无关:而不是特定于平台。
通用:是指独立于平台的。独立于平台的代码/资产组装在一个普通的项目。
查看:指窗口 -level视图。Android使用术语活动,而JavaFX的名字,叫作场景。
组件:是指布局或控制,如的LinearLayout / TextView的/的ImageView在Android或HBox中/垂直框/标签/ ImageView的 JavaFX中。
节点:为了避免使用中的框架特定领域的术语(egCard),通用的术语节 点将被使用。
实施(功能#2)
现在,让我们走过来实现功能2所需的步骤- 一个节点(卡)的显示细节。
 
序列图和术语的定义可以被发现在上一节。
 
[JavaFX的]
 
我宁愿先建JavaFX项目以便采取在调试利用其迅捷的。当您需要确认Android功能,可以如你所愿交换机的优先级。
 
0.Fix在序列图中示出的类/实例,尤其是平台特定的:
 
L0:平台特有的 “自适应”应用类:。com.thinkalike.jfx ThinkAlikeApp
应用程序的入口。它继承原生应用类(javafx.application),并实现独立于平台的平台接口(以便提供特定于平台的数据/方法将通用模块)
L1:特定于平台的原生景观类:如javafx.scene.layout。AnchorPane
底图机类的主窗口。
L2:平台特有的 “自适应”视图类:如。com.thinkalike.jfx.view MainScene
继承了L1的原生UI的功能,并与L7(ViewModel类,如下所述)通过的iProperty / ICommand的事件处理接口交互。
L3:特定于平台的本机组件类:如。javafx.scene.image 的ImageView
底图机类的布局/控制,包括显示节点(卡)图像视图。
L4:平台特有的 “自适应”组件类:如com.thinkalike.jfx.control。ImageNodeView
继承L3重用天然功能,同时满足L5(Component接口,如下所述)的要求,以便更新基于ComponentModel实例的数据(根类是基础组件视图UINode)。
L5:独立于平台的组件接口:如com.thinkalike.generic.viewmodel.control。IImageNodeView
声明要求“自适应”组件类必须满足,一般更新(UINode)接口。
L6:独立于平台的 ComponentModel类:如com.thinkalike.generic.viewmodel.control。UIImageNode
包括UI相关的数据/方法。有些UINode可持有只读“门面”(基本接口是INodeRO)后台数据的对象。
L7:独立于平台的视图模型类:如com.thinkalike.generic.viewmodel。WorkareaViewModel
通常单,并通过相关的L2(“适应性”视图类)实例化。它包括实施IPropery(包括事件注册/ unregist /提交),以及交易的ICommand(检索数据对象,封装视图对象,并提交的iProperty更改事件的所有监听活着)。
L8:独立于平台的数据类:例如。com.thinkalike.generic.domain ImageNode
包括域名相关的数据/方法,通常限制了它的可视图模型层内,以上限制地,(域)模型层。
L9:独立于平台的 DAO类:如com.thinkalike.generic.viewmodel。NodeLoader
持续的数据和数据对象之间进行转换。其可也仅限于视图模型层(域)模型层。
1.首先(和最直观的)步骤,是乱涂的使用故事的非逻辑的UI(功能#2)
 
UI标记文件 - 的JavaFX
 
FX:ID =“inv_nodeContent”标识图像元件,它示出了由用户选择的节点(卡)的细节。请注意,ImageNodeView不是JavaFX的本地类,但“自适应组件类”(L4)。JavaFX的允许直接受雇于UI标记文件的自定义布局/ Control类(如Android的做),使非逻辑UI / UX和逻辑开发者之间彻底的分工。
 
UI布局:\ SRC \ COM \ thinkalike \ JFX \水库\布局\ scene_main.fxml
以上是关于功能#2(命名为UI区号段“工作区”)。应该放置在声明视图(整个布局的FXML文件L2)。FXML的标记语言,简单易学为那些谁拥有经验,HTML / XAML / Android的XML标记。在JavaFX的UI编程(Java或标记)快速启动,你可以参考知识要求分条。
UI风格:\ SRC \ COM \ thinkalike \ JFX \水库\ style_dark.css(黑暗风格)
JavaFX的大量采用层叠样式表(CSS)的优势。有W3C CSS知识就可以轻松掌握与供应商的装饰“-fx-”为前缀的JavaFX的等值Web开发人员。(是的,它比Android的更容易给我。)
2.Associate特定于平台的*自适应View类(L2),其对应的独立于平台的 ViewModel类(L7),用于处理的iProperty更改事件。
 
SD_ThinkAlike_MVVM_IProperty
 
 
// com.thinkalike.jfx.ThinkAlikeApp
 com.thinkalike.jfx.view.MainScene =
        (MainScene)replacePrimarySceneContent(Res.getLayoutUrl( “ scene_main.fxml” ));
MainScene是主机自适应视图(场景指活动在JavaFX中)。该FXML文件的URL是采取实例化。
 
com.thinkalike.jfx.res.Res是特定于平台的实用工具类。资源/资产管理代码已经超出了本文的主线程但是,您可以检查源代码包的详细信息。
 
 
// com.thinkalike.jfx.view.MainScene
 @FXML 
com.thinkalike.jfx.control.ImageNodeView inv_nodeContent;
在JavaFX中,视图类申报组件(场),这些相关FXML标记,以这种方式实例变量。该inv_nodeContent然后将被分配到具有相同名称的组件(FX:ID =“inv_nodeContent” )时自动被解析FXML。
 
 
// com.thinkalike.jfx.view.MainScene
 _vm_workarea = com.thinkalike.generic.viewmodel.WorkareaViewModel.getInstance();
跨平台MVVM项目的真实核心视图模型类,通 常是实例化为单由其响应查看实例中的一个,并具有较长的生命周期。
 
要处理的iProperty事件:节点(卡)在工作区的中间已被更改。
平台特定的*自适应View类的实例:@(发生在)特定于平台的*自适应应用类(L0)
平台特定的*自适应组件类的实例化:// @特定于平台的*自适应View类(L2)
(参考)的实例化与平台无关的 ViewModel类:@特定于平台的*自适应View类(L2)
物业维修事件:@ 与平台无关的 ViewModel类(L7)
 
//com.thinkalike.jfx.view.MainScene
_listenToVM_workarea = new PropertyChangeListener(){
    @Override
    public void onPropertyChanged(PropertyChangeEvent event) {...}
};
_vm_workarea.addPropertyChangeListener(Constant.PropertyName.Node, 
                                        _listenToVM_workarea);
_listenToVM_workarea被实例化来处理一个简单的onPropertyChanged()回调接口。然后,它赞同有关视图模型(_vm_workarea),听取有关特定财产的事件。Constant.PropertyName.Node标识的财产,并在视图模型的基础没有重复。对于重量级应用,EventBus图案将是有用的。 
 
 
//com.thinkalike.generic.viewmodel.WorkareaViewModel
this.firePropertyChange(Constant.PropertyName.Node, oldValue, _uiNode);
当视图模型已经准备了一个新的视图对象或ComponentModel(egUIImageNode),其提交属性更改事件与对象作为参数。
 
事件注册(由特定于平台的*自适应View类(称为L2)):
注销事件:尚未使用。
欲了解更多实施细节,有一个PropertyChangeListenerAdapter管理WeakReference的地图,以避免被淘汰通知事件侦听器。您可以致电removePropertyChangeListener()有意取消事件订阅为好。 
事件提交:
物业事件处理:@特定于平台的*自适应View类(L2)和自适应组件类(L4)
隐藏   复制代码
//com.thinkalike.jfx.view.MainScene
@Override
public void onPropertyChanged(PropertyChangeEvent event) {
    if (event.getPropertyName().equals(Constant.PropertyName.Node)){
        updateWorkarea((UINode)event.getNewValue());
    }
}
当被通知节点发生了变化,自适应View类将事件参数转换成内部方法的参数。
 
有两种方法来通用ComponentModel对象供给到代表层:
 
在这两种情况下,自适应Component类(的实例L4)将调用更新(UINode)来更新自身。最后,底层的本地组件类(L3)将接受翻译信息从ComponentModel做实际的渲染。在这点上,ComponentModel(属于一般的模块)应当被设计为能够容纳特定平台的视图类的不同需求。例如,在ImageView的的情况下,机器人和JavaFX对相对尺寸测量不同的程序(JavaFX的不具有onPreDraw()回调)和异步图像加载(JavaFX的支持它默认,而Android没有)。因此,开发商必须研究每个平台的策略,以找到合适的出路。很高兴,这样的工作需要一次只完成(每种成分的,不同的非功能性需求)。JavaFX的:
 
 
//com.thinkalike.jfx.control.ImageNodeView
protected static void update(UINode uiData, ImageView rawView) {
    if(uiData instanceof UIImageNode){
        //0.initialize according to context.
        int width_limit, height_limit;
        width_limit = (int)rawView.getFitWidth();
        height_limit = (int)rawView.getFitHeight();
        
        //1.set the default image: 
        rawView.setImage(new Image(Res.getImageUrl("default_image.gif")));
 
        //2.Async load Image: 
        final String imageUrl = Util.getAbsoluteUrl(((UIImageNode)uiData).getRelativePath());
        Image image = Util.decodeThumbFromFile(imageUrl, width_limit, height_limit);
        rawView.setImage(image);
    }
}
事件处理:
UI更新:
UINode.attachView(INodeView)
如果自适应元器件实例已经存在(如在的情况下NodeContent),ComponentModel可以连接到它。 
UINode.createView()
否则,如果没有一个自适应组件,ComponentModel可以要求相关类型Component类的动态实例化(如在细胞中的情况下NodeSelector)。厂类将实例上要求适当平台特定* Component类。
3.Make平台特有的自适应* View类(L2)翻译用户的命令操作ICommand的事件这是可以理解到相应的平台无关的ViewModel类(L7)
 
SD_ThinkAlike_MVVM_ICommand(点击放大)
 
 
//com.thinkalike.jfx.view.MainScene
this.lv_nodeList.getSelectionModel().selectedItemProperty().addListener(
        new ChangeListener<UINode>() {
            public void changed(ObservableValue< extends UINode> ov, 
                    UINode old_val, UINode new_val) {
                if(_vm_nodeSelector!=null){
                    _vm_nodeSelector.onNodeSelected(new_val);
                }
            }
        });
当用户交互发生在NodeSelector,上面的ChangeListener将收到通知从本地ListView控件(lv_nodeList),然后激活的ICommand(onNodeSelected()相关的视图模型(中)_vm_nodeSelector:NodeSelectorViewModel)。如上所述,一个EventBus图案都可以在这里使用的两种的iProperty和ICommand的事件。在简化的情况下,但是,一个同步的方法调用工作为好。
 
 
//com.thinkalike.generic.viewmodel.NodeSelectorViewModel
public void onNodeSelected(UINode uiNode){
    INodeRO oldValue = _nodeSelected_RO;
    _nodeSelected_RO = uiNode.getDataRO();
    this.firePropertyChange(Constant.PropertyName.Node, oldValue, _nodeSelected_RO);
}
在接受ICommand的事件,NodeSelectorViewModel检索“只读数据接口”(INodeRO从)UINode。这是因为UINode,作为查看对象,具有不能由其他UI被简单地再利用它自己的UI上下文(例如,在这种情况下,在列表中小区节点将具有比在工作区域中的较小的默认大小),和因此具有暴露底层数据对象传输。的INodeRO,或只是节点,如果访问权限不考虑,将用于在这种情况下提出IPropery变化事件。
 
//com.thinkalike.generic.viewmodel.WorkareaViewModel
_listenToVM_nodeSelector = new PropertyChangeListener(){
    @Override
    public void onPropertyChanged(PropertyChangeEvent event) {
        thisInstance.setNodeRO((INodeRO)event.getNewValue());
    }
};
...
private void setNodeRO(INodeRO nodeRO){
    Object uiContext = Loader.getInstance().getPlatform().getUIContext();
    if(nodeRO instanceof ImageNode.RO){
        ImageNode node = new ImageNode(((ImageNode.RO)nodeRO).getRelativePath()); 
        UIImageNode uiNode = new UIImageNode(uiContext, node, false); 
        setUINode(uiNode);
    }
    else if(nodeRO == null){
        setUINode(null);
    }
}
WorkareaViewModel监听NodeSelectorViewModel,接收实际数据对象的只读接口,创建临时数据对象和表示上焦点的节点(卡)查看对象,并回收旧的。
 
被激活的ICommand事件:选定的节点(卡)中NodeSelector已经改变。
用户的命令的操作:在NodeSelector区域选定节点(卡)(窗口的左侧)已被更改。
ICommand的事件激活:@特定于平台的*自适应View类(L2)
ICommand的事件处理:@ 与平台无关的 ViewModel类(L7)
4.调试,原生API,调研究细节,并达到目标。
 
ThinkAlike的JavaFX
 
直到现在,功能2在JavaFX项目已经完成。不论这个建筑站起来平台迁移可以在Android项目的开发进行测试。
 
[Android版]
 
开发步骤类似于以前的(JavaFX的的),以一个大的程度上,这证明跨平台解决方案的好处。因此,我只需要更换,并指定更改的一部分。
 
0.Fix在序列图中所示的类/实例
 
L0:平台特有的 “自适应”应用类:。com.thinkalike.android ThinkAlikeApp
L1:特定于平台的原生景观类:如。android.support.v4.app 片段
片段中的Android能够为不同的移动设备自适应布局。
L2:平台特有的 “自适应”视图类:如com.thinkalike.android.view。WorkareaFragment
L3:特定于平台的本机组件类:如。android.widget 的ImageView
L4:平台特有的 “自适应”组件类:如com.thinkalike.android.control。ImageNodeView
L5:独立于平台的组件接口:如com.thinkalike.generic.viewmodel.control。IImageNodeView
L6:独立于平台的组件类:如com.thinkalike.generic.viewmodel.control。UIImageNode
L7:独立于平台的视图模型类:如com.thinkalike.generic.viewmodel。WorkareaViewModel
L8:独立于平台的数据类:例如。com.thinkalike.generic.domain ImageNode
L9:独立于平台的 DAO类:如com.thinkalike.generic.viewmodel。NodeLoader
毫无疑问,L5-L9,这5个级别将耗资ZERO在平台迁移。
 
1.Implement使用故事的非逻辑的UI(功能#2)
 
 
 
<LinearLayout
    android:id="@+id/ll_work_overlay"
    android:gravity="center_horizontal"
    android:orientation="vertical">
    ...
    <com.thinkalike.android.control.ImageNodeView
        android:id="@+id/iv_nodecontent"
        ... />
    ...
</LinearLayout>
Android使用的UI标记文件的XML。机器人:ID =“@ + ID / iv_nodecontent”标识对应节点(卡)的细节图像控制。
 
ImageNodeView是一种自适应组件类(L4)平行于JavaFX中。
 
UI布局:\水库\布局\ workarea.xml
UI风格:N / A。相比之下,JavaFX的缩短了在这个领域的学习曲线。
2.Associate特定于平台的*自适应View类(L2),其对应的独立于平台的 ViewModel类(L7),用于处理的iProperty更改事件。
 
 
//AndroidManifest.xml
 < application 
    android:name =" .android.ThinkAlikeApp" > 
    < activity 
        android:name =" .android.view.MainActivity" 
        android:screenOrientation =" landscape"  > 
        < intent-filter > 
            < action  android:name =" android.intent.action.MAIN"  / > 
            < category  android:name =" android.intent.category.LAUNCHER"  / > 
        < /intent-filter > 
    < /activity > 
< /application >
Android开发者都知道,活动课(关联的实例意图)和Application类是基于的清单信息的AndroidManifest.xml,这是JavaFX应用程序不同。
 
 
//\res\layout\activity_main_twopane.xml
 < LinearLayout 
    android:id =" @+id/ll_twopane" > 
    < fragment 
        android:id =" @+id/nodeselector" 
        android:name =" com.thinkalike.android.view.NodeSelectorFragment" 
        ...  / > 
    < fragment 
        android:id =" @+id/workarea" 
        android:name =" com.thinkalike.android.view.WorkareaFragment" 
        ...  / > 
< /LinearLayout >
在功能#2中的直接父窗口,但是,是WorkareFragment,如设计在UI标记文件。
 
 
// com.thinkalike.android.view.WorkareaFragment
 com.thinkalike.android.control.ImageNodeView _inv_nodecontent =
        (ImageNodeView)rootView.findViewById(R.id.iv_nodecontent);
 
// com.thinkalike.android.view.WorkareaFragment
 com.thinkalike.generic.viewmodel.WorkareaViewModel _viewModel =
        WorkareaViewModel.getInstance();
要处理的iProperty事件:节点(卡)在工作区的中间已被更改。
平台特定的*自适应View类的实例:@(在发生)特定于平台的*自适应应用类(L0)
平台特定的*自适应组件类的实例化:// @特定于平台的*自适应View类(L2)
(参考)的实例化与平台无关的 ViewModel类:@特定于平台的*自适应View类(L2)
物业维修事件:@ 与平台无关的 ViewModel类(L7)
//com.thinkalike.android.view.WorkareaFragment
_listenToVM = new PropertyChangeListener(){
    @Override
    public void onPropertyChanged(PropertyChangeEvent event) {...}
};
_viewModel.addPropertyChangeListener(Constant.PropertyName.Node,
                            _listenToVM);
//com.thinkalike.generic.viewmodel.WorkareaViewModel
this.firePropertyChange(Constant.PropertyName.Node, oldValue, _uiNode);
事件注册(由特定于平台的*自适应View类(称为L2)):
注销事件:未使用。
事件提交:
物业事件处理:@特定于平台的*自适应View类(L2)和自适应组件类(L4)
 
//com.thinkalike.android.view.WorkareaFragment
@Override
public void onPropertyChanged(PropertyChangeEvent event) {
    if (event.getPropertyName().equals(Constant.PropertyName.Node)){
        updateWorkarea((UINode)event.getNewValue());
    }
}
作为JavaFX的实现,自适应组件类(讨论如何L4,如ImageNodeView)转换的ComponentModel(UIImageNode),将其提供给本机组件类(L3,比如ImageView的)取决于特定于平台的GUI * API接口。Android有OnPreDrawListener.onPreDraw()可用于实际渲染的ImageView之前检索父视图的尺寸。本次交易被封装到自适应组件类(ImageNodeView):
 
隐藏   复制代码
//com.thinkalike.android.control.ImageNodeView
final ImageNodeView thisInstance = this;
...
@Override
public boolean onPreDraw() {
    thisInstance.getViewTreeObserver().removeOnPreDrawListener(this);
    int width_image = Util.getActualLayoutWidth(thisInstance);
    int height_image = Util.getActualLayoutHeight(thisInstance);
    MediaAsyncLoader.asyncLoadImageFile(imagePath, width_image, height_image, _onMediaLoadListener);
    return true;
}
事件处理:
UI更新:
3.Make平台特有的自适应* View类(L2)翻译用户的命令操作ICommand的事件这是可以理解到相应的平台无关的ViewModel类(L7)
 
 
//com.thinkalike.android.view.NodeSelectorFragment
...
_lv_nodeList.setOnItemClickListener(this);
...
@Override
public void onItemClick(AdapterView<> parent, View view, int position, long id) {
    assert(parent.getAdapter() instanceof NodeAdapter);
    NodeAdapter adapter = (NodeAdapter)parent.getAdapter();
    UINode uiNode = (UINode)adapter.getItem(position);
    if(_viewModel!=null)
        _viewModel.onNodeSelected(uiNode);
}
到JavaFX项目类似,用户的命令操作将发生在本机ListView控件(_lv_nodeList),然后激活的ICommand(onNodeSelected()相关的视图模型)(_viewModel:NodeSelectorViewModel)。
 
被激活的ICommand事件:选定的节点(卡)中NodeSelector已经改变。
用户的命令的操作:在NodeSelector区域选定节点(卡)(窗口的左侧)已被更改。
ICommand的事件激活:@特定于平台的*自适应View类(L2)
ICommand的事件处理:@ 与平台无关的 ViewModel类(L7)
怎样的故事NodeSelectorViewModel接受ICommand的要求,变换参数,并将其指派到它的听众WorkareaViewModel只是相同的JavaFX项目。 独立于平台的代码,不需要只要UI逻辑保持真正的更新。
4.Debug,原生API,调研究细节,并达到目标。ThinkAlike的Android
 
分配
具体来说,分发JavaFX应用程序无辜JRE / JDK的平台被证实是可行的。
 
这是一个不可不看的上的JavaFX项目的跨平台分发Eclipse用户(适用于Windows和MacOS): JavaFX的2教程第七部分-部署有了E(FX)clipse 在ThinkAlike项目,因为“联源文件夹”的使用和不能被蚂蚁(默认库在Eclipse)来解决,一些手动修改应当在作出build.xml文件: 
 
project.loc是你应该添加到Eclipse的首选项(首选项>蚂蚁>运行>属性选项卡)同值的Ant属性$ {} project_loc(预定义的Eclipse变量)。
在Mac OS部署(炉边支持MacOS X的为好)只被通过安装官方的JavaFX合奏示例应用程序进行测试。对MacOS的测试ThinkAlike的任何努力将非常感激。
 
结论
因此,在这篇文章中,我讨论了落实使用MVVM,Android SDK和了解JavaFX SDK的Android的桌面跨平台应用的可能性。一卡参考库已经建立起来,它希望可以在你喜欢的炉石的网络游戏中使用。
 
ThinkAlike来源,请访问:https://github.com/tiancheng2000/ThinkAlike 
炉边纸牌游戏的官方网站:http://us.battle.net/hearthstone/en/
 
对于未来的改进:1.improving框架接口2.more独立于平台的组件类,以及从通用代码3.EventBus被实例化。
 
该卡的游戏是免费的,该框架是免费的,而创造和解决问题的乐趣将是无价的
 
确认
 
这是我的第一篇到CodeProject。感谢社区编辑“好心帮两个技术和语言的观点!还要感谢给予我的妻子,谁没有IT的语言知识,但支持我,“调试”我的英语语法。无论我们说何种语言,“本土”与否,我希望在有趣的东西,我们“略同”。
 

上一篇:RecyclerView中Adapter和ViewHolder的封装
下一篇:安卓开发一次解决OOM的经历

相关内容

热门推荐