Dorado 5 : 4.2.Dataset Listener使用详解 (T32)

Dataset Listener事件使用详解

下面对监听器类里面每个方法进行解析一下:

方法

说明

void onInit(Dataset dataset)

Dataset的初始化方法。此方法在Dataset.init中最后触发的,也就是说在Dataset根据view.xml被创建的时候才触发

boolean beforeCreateFields(Dataset dataset)

Dataset一般是通过本身的doLoad方法来创建字段和加载数据的,如设定了autoCreateFields为true或者在view.xml里没有设定fields,则触发该方法

void afterCreateFields(Dataset dataset)

如果进入了beforeCreateFields方法处理完返回的值是true,那么Dataset将进入doLoad方法来创建字段和加载数据,处理完之后就触发该方法,也就是说如beforeCreateFields没被触发或者beforeCreateFields返回false都不会触发该方法

boolean beforeLoadData(Dataset dataset)

Dataset在页面初始化时设定autoLoadData为true或者通过ajax来加载数据的时候,在加载数据(doLoad)之前会触发该方法,如该方法返回true才进入doLoad加载数据

void afterLoadData(Dataset dataset)

Dataset在做完beforeLoadData和doLoad(不一定要触发doLoad)之后才触发的事件,如触发过beforeLoadData才会触发本方法

boolean beforeUpdateData(Dataset dataset)

当Dataset执行update方法的时候触发,在更新数据(doUpdate)之前会触发该方法,如该方法返回true才进入doUpdate更新数据

void afterUpdateData(Dataset dataset)

Dataset在做完beforeUpdateData和doUpdate(不一定要触发doUpdate)之后才触发的事件

以上方法不是在所有情况都会被执行的。
我们根据上面表格对Dataset Listener里各种方法的说明,可以很清楚地知道每个方法的作用:

  1. onInit

该方法一般会处理一些Dataset的属性设置,比如你想在进入ViewModel的initDataset之前就修改Dataset在view.xml的配置信息。

  1. beforeLoadData

该方法一般是处理Dataset在加载数据之前改变Dataset为了取到数据而需要的属性,或者直接在这个方法里加载数据。
在本方法里改变Dataset的属性或者上下文来确定Dataset怎样取到数据,这里一般返回true。
在本方法里加载数据,而不需要Dataset的默认加载方式,这里一般返回false,最常用该方法的Dataset是CustomDataset。

  1. beforeCreateFields

这里一般会返回true或者false来决定Fields由本方法来创建还是让Dataset的doLoad方法来创建。
在本方法中对Dataset创建了一些Fields,不想让Dataset执行默认的创建Fields,则返回false;既想对Dataset创建了一些Fields,又想让Dataset执行默认的创建Fields,那则返回true。

  1. afterCreateFields

本方法在Dataset的doLoad做完之后触发的,所以一般不会使用本方法来处理Fields,除非你想在doLoad的时候需要的Fields和出现到页面时的Fields不同,或者在之前加载Fields在doLoad所需要的属性,在本方法里才加载Fields的显示属性。

  1. afterLoadData

本方法是在b、c、d完成直接触发的方法,本方法触发的条件是b) beforeLoadData必须触发,在c与d中间可能会执行Dataset的load方法来获取数据。
本方法一般是处理获取到数据之后来对结果操作,比如有些数据获取到Dataset之后才对Records做筛选才展现到页面,或者对Records做修改才显示到页面等等。

  1. beforeUpdateData

本方法是通过Dataset.update触发的,一般是Dataset封装了update的处理才进入处理。一般会在AutoSqlDataset和SqlDataset中用到,因为这些Dataset一般不需要我们通过UpdateCommand在ViewModel.java定义Method来提交数据。如你要通过UpdateCommand在ViewModel.java定义Method来提交数据又想触发本方法,请在UpdateCommand的Method方法中调用super.doUpdateData(parameters, outParameters);通过super.doUpdateData会执行Dataset.update,从而触发本方法。
该方法一般是处理Dataset在提交数据之前改变Dataset的记录集,或者直接在这个方法里提交数据。
在本方法里改变Dataset的记录集,这里一般返回true。
在本方法里提交数据,而不需要Dataset的默认提交方式,这里一般返回false

  1. afterUpdateData

触发原理跟f)一样。
本方法一般是处理提交数据之后来对结果操作,比如有些数据提交到Dataset之后才对Records做筛选才展现到页面,或者对Records做修改才显示到页面等等,最常见的是自动Id的获取。

Dataset Listener高级用法

我们在4.2.1中已经了解到Listener中大概分成3个不同地方触发的事件:一个是onInit;一个是beforeLoadData、beforeCreateFields、afterCreateFields、afterLoadData;另一个是beforeUpdateData、afterUpdateData。
onInit是在ViewModel根据view.xml创建Dataset的时候触发的,但又在initDataset之前,所以Listener的onInit事件的触发只能在view.xml配置Dataset的Listener,想在java代码中动态添加Listener就相对不可能了。
beforeLoadData、beforeCreateFields、afterCreateFields、afterLoadData是在Dataset获取数据的时候触发的,所以在view.xml配置Dataset的Listener或者在Dataset执行Load之前添加都可以。
beforeUpdateData、afterUpdateData是在Dataset提交数据的时候触发的,所以在view.xml配置Dataset的Listener或者在Dataset执行update之前添加都可以。

动态给Dataset添加Listener

根据上面的说明,可以清楚地知道想在Listener中处理哪些事件,就在相应的触发事件前给Dataset添加Listener。比较常用的是在ViewModel的initDataset中对Dataset添加Listener。

 protected void initDataset(ViewDataset dataset) throws Exception {
        // TODO Auto-generated method stub
        super.initDataset(dataset);
        if ("datasetCustom".equals(dataset.getId())) {
            DatasetListener datasetListener = new CustomDatasetListener();
            dataset.addDatasetListener(datasetListener);
        }
  }

代码 4.1:ViewModel的initDataset中对Dataset添加Listener

给Dataset添加多个Listener

Dataset中Listener是可以设置多个的,所以其实Dataset是执行Listeners。Listeners是一个堆栈,当Dataset执行Listeners事件的时候,Dataset会对每个Listener的事件都处理一次,直到处理完所有Listeners。
当多个Listener组成Dataset的Listeners时,事件中没有返回值的是每个Listener都执行的,有返回值时当有一个返回值是false的时候就终止了该事件往下的执行,后面将要执行的Listener该事件将不会执行。
下面的例子当中,view.xml中已经对Dataset配置了一个Listener(通过";"还可以配置多个Listeners),在ViewModel的initDataset中还动态地添加一个Listener:

图 4.1:view.xml对Dataset配置一个Listener

 public class Sample2_1ViewModel extends DefaultViewModel {
    public void init(int arg0) throws Exception {
        super.init(arg0);
    }
    protected void initDataset(ViewDataset dataset) throws Exception {
        super.initDataset(dataset);
        if ("datasetCustom".equals(dataset.getId())) {
            DatasetListener datasetListener = new CustomDatasetListener2();
            dataset.addDatasetListener(datasetListener);
        }
    }
}

代码 4.2:ViewModel的initDataset中对Dataset增加Listener

package com.bstek.dorado5.docent.chapter2;
import com.bstek.dorado.data.AbstractDatasetListener;
import com.bstek.dorado.data.Dataset;
public class CustomDatasetListener extends AbstractDatasetListener {
    public void onInit(Dataset dataset) throws Exception {
        super.onInit(dataset);
    }
    public void afterCreateFields(Dataset dataset) throws Exception {
        super.afterCreateFields(dataset);
    }
    public void afterLoadData(Dataset dataset) throws Exception {
        super.afterLoadData(dataset);
    }
    public void afterUpdateData(Dataset dataset) throws Exception {
        super.afterUpdateData(dataset);
    }
    public boolean beforeCreateFields(Dataset dataset) throws Exception {
        return super.beforeCreateFields(dataset); // true
    }
    public boolean beforeLoadData(Dataset dataset) throws Exception {
        return true;
    }
    public boolean beforeUpdateData(Dataset dataset) throws Exception {
        return super.beforeUpdateData(dataset); // true
    }
}

代码 4.3:CustomDatasetListener代码

package com.bstek.dorado5.docent.chapter2;
import com.bstek.dorado.data.AbstractDatasetListener;
import com.bstek.dorado.data.Dataset;
import com.bstek.dorado.data.ParameterSet;
import com.bstek.dorado.data.Record;
import com.bstek.dorado.utils.StringHelper;
public class CustomDatasetListener2 extends AbstractDatasetListener {
    public void onInit(Dataset dataset) throws Exception {
        super.onInit(dataset);
    }
    public void afterCreateFields(Dataset dataset) throws Exception {
        super.afterCreateFields(dataset);
    }
    public void afterLoadData(Dataset dataset) throws Exception {
        super.afterLoadData(dataset);
    }
    public void afterUpdateData(Dataset dataset) throws Exception {
        super.afterUpdateData(dataset);
    }
    public boolean beforeCreateFields(Dataset dataset) throws Exception {
        return super.beforeCreateFields(dataset);
    }
    public boolean beforeLoadData(Dataset dataset) throws Exception {
        ParameterSet parameters = dataset.parameters();
        String EMPLOYEE_ID = parameters.getString("EMPLOYEE_ID");
        String DEPT_ID = parameters.getString("DEPT_ID");
        // 模拟查询数据
        if (StringHelper.isNotEmpty(EMPLOYEE_ID)
                || StringHelper.isNotEmpty(DEPT_ID)) {
            Record record = dataset.insertRecord();
            record.setString("EMPLOYEE_ID", EMPLOYEE_ID);
            record.setString("DEPT_ID", DEPT_ID);
        } else {
            Record record = dataset.insertRecord();
            record.setString("EMPLOYEE_ID", "Default");
            record.setString("DEPT_ID", "Default");
            record = dataset.insertRecord();
            record.setString("EMPLOYEE_ID", "Default2");
            record.setString("DEPT_ID", "Default2");
        }
        return false;
    }
    public boolean beforeUpdateData(Dataset dataset) throws Exception {
        return super.beforeUpdateData(dataset);
    }
}

 

代码 4.4:CustomDatasetListener代码
通过上面的代码可以看见ViewModel的时候,通过一个配置和一个动态加载使datasetCustom添加了两个Listener,当Dataset执行Listeners事件的时候,会把所有的Listeners同一事件不同的顺序执行,比如上面例子当中执行Listener的onInit事件,就会先执行CustomDatasetListener的onInit事件,然后再执行CustomDatasetListene2r的onInit事件,当两个都执行完之后,Listener的onInit事件才是正在的执行完毕。当事件中有返回值的时候,Listener的执行会根据返回值来确定要不要继续执行不同Listener的同一事件,比如上面例子中的beforeLoadData事件,Dataset Listener先执行CustomDatasetListener的beforeLoadData事件,因为该事件中返回true,所以继续往下执行剩下的Listener beforeLoadData事件,因此再执行CustomDatasetListener2的beforeLoadData事件。由于CustomDatasetListener2的beforeLoadData事件返回false,所以总的beforeLoadData事件返回false,这个返回值会影响到后面Dataset的LoadData的执行。我们再把CustomDatasetListener和CustomDatasetListener2的顺序换一下,也就是说把他们添加在Dataset的顺序换一下,那么先执行CustomDatasetListener2的beforeLoadData事件,这个时候就已经返回false,那么下面CustomDatasetListener的beforeLoadData事件就不会再执行,总的beforeLoadData事件也返回false。