【一起学UniGUI】--UniGUI的窗体和模块(8)-程序员宅基地

技术标签: UniGUI  

(六)、数据模块(DataModules):

       uniGUI支持向项目中添加数据模块(DataModules)。它允许开发人员像标准VCL应用程序那样设计他们的应用程序,将应用程序业务逻辑划分为几个数据模块。需要记住的重要一点是,虽然uniGUI数据模块与标准VCL数据模块在本质上是相同的,但是当使用uniGUI向导创建它们时,它们将为每个会话自动管理(其生存期将与会话本身相同)。如果使用标准IDE创建数据模型,则开发人员须要在适当的时候创建并释放它,并且有可能还是各会话共用(如果开发者不额外处理的话),须解决多会话间冲突问题。

      uniGUI中有两种类型的数据模块。 分别为:应用程序数据模块(Application DataModule) 与 自由数据模块(Free DataModule)。在下面的章节中,我会分子类进行讲述。

1)、应用程序数据模块(Application DataModule)

     应用程序数据模块(Application DataModule)是一个由uniGUI在运行时额外自动生成的,有如下几个特点:

  • 它在应用程序运行初始化时注册生成的
  • 它是在每个会话的开始或按需创建的(依据属性MainModule.ApplicationDataModuleOptions.CreateOnDemand),一个会话对应一个
  • 如果用户不手动释放(使用Free),则在关闭某对应会话时会相对应的自动释放(属于A会话的,在A会话关闭时,会自动释放A对应的应用程序数据模块)

       需要额外数据模型的小型应用程序(比如,多个MainModule)可能会使用缺省值(CreateOnDemand=False),但是大型应用程序将享受更好的内存管理,可以按需创建数据模型(并尽快释放它们)。

这是应用程序中DataModule自动生成的代码:

unit _AppDM1;
 
interface
 
uses
  SysUtils, Classes, FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Param,
  FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf, FireDAC.DApt.Intf,
  Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client, FireDAC.Stan.StorageBin;
 
type
  TAppDM1 = class(TDataModule)
    tblList: TFDMemTable;
    tblListID: TAutoIncField;
    tblListText: TStringField;
    dsList: TDataSource;
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
function AppDM1: TAppDM1;
 
implementation
 
{$R *.dfm}
 
uses
  UniGUIVars, uniGUIMainModule, MainModule;
 

// 这个函数返回一个TAppDM1数据模块实例

// MainModule.ApplicationDataModuleOptions.CreateOnDemandTrue,如果尚未创建datamodule实例,

// 这个函数将创建一个实例并返回给它,否则它将返回先前创建的实例。

// MainModule.ApplicationDataModuleOptions.CreateOnDemandFalse。这个函数在会话启动时直接创建相同的datamodule实例并将返回给它

function AppDM1: TAppDM1;
begin
  Result := TAppDM1(UniMainModule.GetModuleInstance(TAppDM1));
end;
 
initialization
  RegisterModuleClass(TAppDM1);
 
end.

     注意这段代码与应用程序窗体(Application Form)非常相似。
     如果将参数CreateOnDemand设置为true,让我们看看窗体将如何使用应用程序数据模块(Application DataModule)。

unit _TestForm;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, uniGUITypes, uniGUIAbstractClasses,
  uniGUIClasses, uniGUIForm,
  _AppDM1, uniGUIBaseClasses, uniBasicGrid, uniDBGrid;
 
type
  TTestForm = class(TUniForm)
    UniDBGrid1: TUniDBGrid;
    procedure UniFormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
function TestForm: TTestForm;
 
implementation
 
{$R *.dfm}
 
uses
  MainModule, uniGUIApplication;
 
function TestForm: TTestForm;
begin
  Result := TTestForm(UniMainModule.GetFormInstance(TTestForm));
end;
 
procedure TTestForm.UniFormDestroy(Sender: TObject);
begin
  AppDM1.Free;  //如果此数据模块(AppDM1)确实不再使用时或也没有其他窗体使用时,在这里写Free方法进行手工释放也是可以的(但不是必须)

                  //如果此数据模块(AppDM1)被占用了,或者同一会话中的其他几个窗体也使用了它,那么不应该调用Free方法

                  //如果这里没有调用Free方法,则在其所属的会话终止时也会自动释放此数据模块(AppDM1)

end;
 
end.

       在窗体OnDestroy销毁事件中显式进行datamodule释放(也就是说,当窗体不再需要它时)。但是没有代码将UniDBGrid链接到数据模块中。让我们来看看DFM文件:

object TestForm: TTestForm
  Left = 0
  Top = 0
  ClientHeight = 246
  ClientWidth = 477
  Caption = 'Test (using App DM On Demand)'
  OldCreateOrder = False
  MonitoredKeys.Keys = <>
  OnDestroy = UniFormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object UniDBGrid1: TUniDBGrid
    Left = 0
    Top = 0
    Width = 477
    Height = 246
    Hint = ''
    DataSource = AppDM1.dsList
    LoadMask.Message = 'Loading data...'
    Align = alClient
    Anchors = [akLeft, akTop, akRight, akBottom]
    TabOrder = 0
  end
end

该链接在表单设计器中也可见:

数据源(TDataSource)在设计时链接到数据模块。在运行时不需要这样做。
运行应用程序证明它确实在没有内存泄漏的情况下工作(内存不泄漏)。

2)、自由数据模块(Free DataModule) 

      这种自由数据模块型只是一个普通的旧数据模型,即与传统VCL的datamodule一样,须要手工创建和释放它。

unit _FreeDataModule;
 
interface
 
uses
  SysUtils, Classes;
 
type
  TFreeDataModule = class(TDataModule)
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
implementation
 
{$R *.dfm}
 
 
end.

       这种数据模块的使用方法与在常见VCL应用程序中使用的方法相同。用户完全有责任在需要时创建它,并在不再需要时释放它。 使用这种数据模型的原因是,一些非可视组件需要一个主机/容器(或者以这种方式使用它们更容易)。一个很好的例子是报表工具,因为即使用户只将它用于导出报表,它通常也会被放入一个DataModule中。
       使用数据模块的另一个原因是不应该在表示层(TForm、TUniForm、任何窗体)中承载“业务代码”。使用自由的数据模块(Free DataModule)允许开发人员按需处理资源,从而将内存使用量降到最低。
      自由数据模块的使用在FastReport和ReportBuilder等如何使用,我会在后面一些深入的学习中再讲述(计划在报表部分中讲解)。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/gzhubin/article/details/92060816

智能推荐

win10 休眠设置无效_windows10系统电脑点击睡眠没反应的解决方法-程序员宅基地

一些用户反馈自己在使用win10系统笔记本电脑过程中,突然碰到了无法睡眠的情况,不管是盖上屏幕还是在系统中选择睡眠,电脑都无法进行睡眠,根本没有任何反应,该怎么办呢?接下来,系统城小编就为大家带来该问题的具体解决方法!首先可以按方法一进行设置:1、按下Windows+X,依次点击 控制面板-电源选项-选择电源计划-平衡/节能/高性能-更改计划设置-更改高级电源设置-睡眠-允许混合睡眠-更改为关闭,..._休眠无效

Gradle –找不到方法compileOnly-程序员宅基地

Git克隆了一个新项目,Gradle构建并遇到以下错误消息: 终奌站 $ gradle clean buildFAILURE: Build failed with an exception.* Where:Build file '/Users/mkyong/Documents/workspace/hc2/web/build.gradle' line: 25* What we..._could not find method compileonly()

JUnit@Before失效问题_junit before赋值失败-程序员宅基地

原文链接:http://www.cnblogs.com/luzhanshi/p/10965592.html在学习Shiro的过程中需要使用到JUnit@Before注解配合测试,但是无论如何,@Before下面的方法都不按照预期的执行,困扰良久,后来各种百度终于找到根源,今分享于诸公,望能解诸公之急:JUnit官网,在官网中发现了这样一段话:原来是 @Before和@After..._junit before赋值失败

python怎么选取不连续的列_Pandas从datafram中选择不连续列-程序员宅基地

如果要连接df列的子选择,请使用pd.concat:pd.concat([comb.ix[:,0:1],comb.ix[:,17:342]], axis=1)只要索引匹配,这将正确对齐。感谢@iHightPower,您还可以通过传递标签进行子选择:pd.concat([df.ix[:,'Col1':'Col5'],df.ix[:,'Col9':'Col15']],a‌​xis=1)请注意,^{}在..._pandas取断续的几列

GlusterFS预防脑裂机制-程序员宅基地

脑裂简单来说就是两个节点之间的联系断了,A进程写server1,B进程写server2,各写各的,写了都记自己对的,对方错了。脑裂发生时,只能管理员手动判断手动恢复了,gluster采用了quorum的机制尽量预防脑裂的发生。 在什么样的场景会出现脑裂的情况呢,打比方说现在有2个副本,个运行在Node1和node2上,我们都知道写完副本后要通知所有其他的副本我已经写完了,其他的副

操作系统第二章课后题_线程控制块tcb中包含了哪些内容-程序员宅基地

操作系统第二章要点1. 什么是前趋图?为什么要引入前趋图?答:前趋图(Precedence Graph)是一个有向无循环图,记为DAG(Directed Acyclic Graph),用于描述进程之间执行的前后关系。2. 画出下面四条语句的前趋图:S1: a=x+y; S2: b=z+1; S3: c=a-b; S4: w=c+1;答:其前趋图为:3. 为什么程序并发执行会产生间断性..._线程控制块tcb中包含了哪些内容

随便推点

java runtimeexception check,java.lang.RuntimeException: takePicture failed_文笔二杨医生的博客-程序员宅基地

when i do continuous click on Capture button (without any break), getting Runtime Exception how can i resolve this issue ?if its not possible so how may i handle this Exception ? btnCapture = (ImageB...

温度补偿计算公式_测量的温度补偿的原则与方法-程序员宅基地

龙源期刊网http://www.qikan.com.cn测量的温度补偿的原则与方法作者:吕莉陈志远来源:《科技创新导报》2011年第24期摘要:在现代飞机制造过程中,坐标测量机大量地应用于生产和产品检测。由于温度变化对于金属材料几何特性的影响,使温度补偿对于降低测量误差的意义非常巨大。本文以波音飞机的产品公差要求为例,根据温度补偿对于不同精度的测量设备测量结果的影响分析,得出在不同的条件下采用坐标..._温度补偿斜率公式怎么计算

js-程序员宅基地

1. 转换为数字JavaScript是一种松散类型的语言,这意味着我们不必显式指定变量的类型。JavaScript还可根据使用的上下文自由地转换值类型。将值转换为数字,尤其是将字符串转换为数字是很常见的要求,并且可以通过许多方法实现。一元+运算符将字符串类型转换为数字的最简洁的方法是一元+运算符:+"42"//42一元运算是只有一个操作数的运算。操作数位于运算符之前或之后。一元+运算符位于操作数之前,并对操作数求值,如果没有将操作数转换为数字,则会尝试将其转换为数字...

用VC++实现一个文本文件阅读器_c 文本阅读器源码-程序员宅基地

首先新建一个MFC exe,基于对话框工程;设计界面如下;添加按钮单击函数;为对话框类添加成员函数;为列表框添加一个成员变量;添加列表框单击函数;(选中条目后执行的函数;)对话框类头文件手动添加private:TCHAR pszPath[MAX_PATH];对话框类_c 文本阅读器源码

小米盒子刷arm linux,小米盒子刷成原生安卓系统操作步骤详解-程序员宅基地

本帖最后由 山阴路的夏天 于 2017-11-1 10:23 编辑现在的小米盒子虽然在各方面都很受用户的欢迎,但还是有一点一直被吐槽的,那就是广告真的太多了,让整个的用户体验感极速下降,如果你想知道小米盒子如何刷机的话不妨可以跟着以下步骤慢慢来。1.刷机前的准备请确认你的盒子是否适合刷机,具体要求是:硬件:MDZ-18-AA, 也就是我们所说的小米盒子3增强版系统:通刷。目前最新的系统是1.5.3..._小米盒子刷arm linux,小米盒子刷成原生安卓系统操作步骤详解

Linux+Informix后台数据库系统《====》WinXX/ODBC/DELPHI/CBUILDER/VB编程设置-程序员宅基地

昆明市商业银行百大支行微机室 本文假定大家的informix使用是从零起步的,将介绍从零至最大化使用informix的各个详细步骤。 本文中关于vi编辑的内容均放在两行等号之间,你要编辑后存盘.一:下载informix-online数据库服务器LINUX试用系统地址:http://www.intraware.com,注册成为informix试用系统的用户,并告诉正确的email地址,然