Fellow Travellers

在线缓存功能开发分享

万峥嵘
字数统计: 1.3k阅读时长: 5 min
2018/08/05 Share


1. 简介

  1. 离线在线一体化
    数据存储在企业级地理数据库中,通过Arcgis桌面加载后配图处理,并发布到Arcgis for Server中,供移动端设备编辑使用,并可以同步回传版本化存档。
  2. 应用场景
    在没有网络的情况下我们需要用到在线的地图数据进行操作,这些数据需要有一定的时效性,如果采用,打包离线包的方式提前做好离线数据,那时效性相对较差。所以,用在线缓存技术可以支持这一点。


2. 在线缓存的实现逻辑思路

  • 在地图上选定区域,作为需要下载对应离线数据的地图范围(可以设定范围,也可以自定义)
  • 获取下载滴地图服务所需要的具体参数
  • 在本地创建文件,存放下载的数据,以供使用


3. 用到的核心功能类以及说明

  • GeodatabaseSyncTask类,实现下载同步功能
  • GenerateGeodatabaseParameters,下载数据时所需的参数对象,该类构造函数一共有7个根据需要选择
    image.png
  • CallbackListener,完成GDB数据库下载的回调函数类,在该回调中我们只可以执行一些操作,如示例里在回调中删除了在线的服务图层,加载离线的数据图层到地图上进行显示。通过Geodatabase本地数据库可以获取要素图层列表List<GdbFeatureTable>对象,通过newFeatureLayer(gdbFeatureTable)来创建一个离线要素图层进行要素显示。
  • GeodatabaseStatusCallback,本地数据库回调状态类,在数据下载过程中会有很多状态改变,各种状态改变时都会走这个类的回调函数。
  • GeodatabaseTask.generateGeodatabase,通过该方法生成离线数据库和相应的要素表,方法需要传递上面介绍的三个参数和一个数据库存储的路径。


4. 代码示例

  1. 在地图上自定义一个区域

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
     /**
    * 绘制出在线缓存区域
    * */
    private void polygonState(Point currentPoint)throws Exception{
    if(startPoint!=null&&!startPoint.isEmpty()){
    polygon.lineTo(currentPoint);
    currentGraphic = new Graphic(polygon, symbol);
    drawLayer.updateGraphic(currentGraphicIndex,currentGraphic);

    pointGraphic=new Graphic(multiPoint,pointSymbol);
    drawLayer.updateGraphic(pointGraphicIndex,pointGraphic);
    multiPoint.add(currentPoint);
    if(lastGraphicIndex!=-1){
    drawLayer.removeGraphic(lastGraphicIndex);
    }
    lastGraphic=new Graphic(currentPoint,lastSymbol);
    lastGraphicIndex=drawLayer.addGraphic(lastGraphic);

    if(polygon.getPointCount()>=3){
    isCheckedSave=true;
    isSave=isCheckedSave;
    onlinesave.setTextColor(ContextCompat.getColor(mActivity,R.color.blue));
    onlinesave.setClickable(isSave);
    }
    }else{
    polygon=new Polygon();
    multiPoint=new MultiPoint();
    polygon.startPath(currentPoint);
    startPoint=currentPoint;
    currentGraphic=new Graphic(startPoint,symbol);
    currentGraphicIndex=drawLayer.addGraphic(currentGraphic);
    pointGraphic=new Graphic(startPoint,lastSymbol);
    pointGraphicIndex=drawLayer.addGraphic(pointGraphic);
    multiPoint.add(currentPoint);
    }
    }
    /**
    * 确定所选区域范围
    * */
    public void SaveLabel()throws Exception{
    if(isSave&&drawLayer!=null) {
    startPoint = null;
    isCheckedSave=false;
    isSave=isCheckedSave;
    onlinesave.setTextColor(ContextCompat.getColor(mActivity,R.color.gray));
    onlinesave.setClickable(isSave);
    if(currentGraphicIndex!=-1){
    Graphic graphic = drawLayer.getGraphic(currentGraphicIndex);
    if(graphic!=null){
    Geometry geometry=graphic.getGeometry();
    Graphic saveGraphic=null;
    if(geometryType.equals(Geometry.Type.POLYGON)){
    symbol=MapViewTapTool.getLabelSymbol(mActivity,geometryType,ContextCompat.getColor(mActivity,R.color.green_transparent));
    saveGraphic=new Graphic(geometry,symbol);
    pointSymbol=MapViewTapTool.getCircleGreenSymbol(mActivity);
    pointGraphic=new Graphic(geometry,pointSymbol);
    }else{
    symbol=MapViewTapTool.getLabelSymbol(mActivity,geometryType,ContextCompat.getColor(mActivity,R.color.green));
    saveGraphic=new Graphic(geometry,symbol);
    pointSymbol=MapViewTapTool.getCircleGreenSymbol(mActivity);
    pointGraphic=new Graphic(geometry,pointSymbol);
    }
    if(onlineCacheInfoList!=null&&onlineCacheInfoList.size()>0){
    setView();
    int i = 0;
    if(onlineCacheInfoList.get(i).getCacheurl().trim().length()>0) {
    downloadData(onlineCacheInfoList.get(i), geometry, i);//缓存featureLayer
    }
    }
    }
    }
    }else{
    isCheckedSave=false;
    isSave=isCheckedSave;
    onlinesave.setTextColor(ContextCompat.getColor(mActivity,R.color.gray));
    onlinesave.setClickable(isSave);
    }
    }
  2. 下载选定区域所对应的在线缓存的文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    private void downloadData(final OnlineCacheInfo onlineCacheInfo, final Geometry geometry, final int i) {
    gdbSyncTask = new GeodatabaseSyncTask(onlineCacheInfo.getCacheurl(), null);
    gdbSyncTask.fetchFeatureServiceInfo(new CallbackListener<FeatureServiceInfo>() {
    @Override
    public void onError(Throwable arg0) {
    Log.e(TAG, "Error fetching FeatureServiceInfo");
    }

    @Override
    public void onCallback(FeatureServiceInfo fsInfo) {
    if (fsInfo.isSyncEnabled()) {
    //回调获取所需要的下载的图层信息
    createGeodatabase(onlineCacheInfo.getIds(),geometry,i);
    }
    }
    });

    }
    //创建下载
    private void createGeodatabase(int[] ids, final Geometry geometry, final int i) {
    SpatialReference sp=mOneMapView.getSpatialReference();
    GenerateGeodatabaseParameters params = new GenerateGeodatabaseParameters(ids, geometry,sp,true, SyncModel.GEODATABASE);

    CallbackListener<String> gdbResponseCallback = new CallbackListener<String>() {
    @Override
    public void onError(final Throwable e) {
    Log.e(TAG, "Error creating geodatabase");
    Toast.makeText(mActivity, "数据下载失败!", Toast.LENGTH_LONG).show();
    pDialog.dismiss();
    }

    @Override
    public void onCallback(String path) {
    updateFeatureLayer(path);
    if(i<onlineCacheInfoList.size()&&onlineCacheInfoList.get(i+1).getCacheurl().trim().length()>0){
    downloadData(onlineCacheInfoList.get(i+1),geometry,i+1);
    }else {
    pDialog.dismiss();
    Toast.makeText(mActivity, "数据下载完成!", Toast.LENGTH_LONG).show();
    }
    }
    };
    localGdbFilePath = "对应在本地存储的存储路径以及存储名称";
    submitTask(params, localGdbFilePath, statusCallback,
    gdbResponseCallback);
    }
    private void submitTask(GenerateGeodatabaseParameters params,
    String file, GeodatabaseStatusCallback statusCallback,
    CallbackListener<String> gdbResponseCallback) {
    // submit task
    gdbSyncTask.generateGeodatabase(params, file, false, statusCallback,
    gdbResponseCallback);
    }
  3. 将下载完成的数据再地图上展示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//加载数据
private void updateFeatureLayer(String featureLayerPath) {
// create a new geodatabase
Geodatabase localGdb = null;
try {
localGdb = new Geodatabase(featureLayerPath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}

if (localGdb != null) {
for (GeodatabaseFeatureTable gdbFeatureTable : localGdb
.getGeodatabaseTables()) {
if (gdbFeatureTable.hasGeometry()){
mOneMapView.addLayer(new FeatureLayer(gdbFeatureTable));
}
}
}
}


5. 结语

在线缓存的应用,减少了手动制作离线数据的步骤,大大提高了地图制作的效率,只需发布对应的地图服务就能实现离线数据的在线下载。另外也同时保证了数据的时效性,如果对应地图服务有新的数据更改,那我们可以重新下载新的在线数据,不需要再去手动打包地图文件。

  • 最后感谢您的阅读,有机会一起探讨!
CATALOG
  1. 1. 1. 简介
  2. 2. 2. 在线缓存的实现逻辑思路
  3. 3. 3. 用到的核心功能类以及说明
  4. 4. 4. 代码示例
  5. 5. 5. 结语