You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ArcGIS SDK 100.2.1离线路线创建报错及旧版本示例适配咨询

解决ArcGIS SDK 100.2.1离线路线创建的"Cannot call this method in this context"错误

首先得说,100.x系列的ArcGIS Runtime SDK和10.2.x的API差异非常大,旧示例的写法完全不适用于新SDK,这是你遇到问题的核心原因。下面我会一步步帮你实现离线路线创建,并解决这个线程上下文的报错。

一、错误原因分析

这个报错几乎都是线程上下文不正确导致的:ArcGIS Runtime SDK 100.x中,所有耗时的地理操作(比如加载本地网络数据集、计算路由)必须在后台线程执行;而涉及UI更新或者组件初始化的部分,必须在主线程完成。如果搞混了线程,就会抛出这个异常。

二、离线路线创建的正确步骤(针对100.2.1)

假设你已经有包含网络数据集的离线地理数据库(.geodatabase),下面是完整的实现流程:

1. 准备离线资源

确保你的离线geodatabase包含:

  • 可用的网络数据集(用于路由计算)
  • 可选的定位点数据(起点、终点)

2. 初始化离线RouteTask

不要在主线程中直接初始化RouteTask或者加载网络数据集,必须用后台线程(比如AsyncTask,100.2.1时期Android还没普及Coroutine,用AsyncTask更稳妥)。

示例代码:

// 在Activity中启动后台加载任务
new RouteLoadTask().execute();

// 后台加载RouteTask的任务类
private class RouteLoadTask extends AsyncTask<Void, Void, RouteTask> {
    @Override
    protected RouteTask doInBackground(Void... voids) {
        try {
            // 本地geodatabase路径(示例为内部存储路径,可根据你的存储位置调整)
            String gdbPath = getFilesDir() + "/your_offline_data.gdb";
            Geodatabase geodatabase = new Geodatabase(gdbPath);
            
            // 替换成你自己的网络数据集名称
            String networkDatasetName = "CityStreets_ND";
            NetworkDataset networkDataset = geodatabase.getNetworkDataset(networkDatasetName);
            
            // 创建离线RouteTask实例
            return RouteTask.createFromNetworkDataset(networkDataset);
        } catch (ArcGISRuntimeException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    protected void onPostExecute(RouteTask routeTask) {
        super.onPostExecute(routeTask);
        if (routeTask != null) {
            // 主线程中处理初始化完成逻辑,比如获取默认路由参数
            getDefaultRouteParams(routeTask);
        } else {
            Toast.makeText(RoutingActivity.this, "离线路由资源加载失败", Toast.LENGTH_SHORT).show();
        }
    }
}

3. 获取路由参数并计算路线

获取默认参数、计算路由的操作都需要在后台线程执行,只有结果处理可以放在主线程:

private void getDefaultRouteParams(RouteTask routeTask) {
    new AsyncTask<RouteTask, Void, RouteParameters>() {
        @Override
        protected RouteParameters doInBackground(RouteTask... routeTasks) {
            try {
                // 获取默认路由参数,必须在后台线程
                return routeTasks[0].createDefaultParameters();
            } catch (ArcGISRuntimeException e) {
                e.printStackTrace();
                return null;
            }
        }

        @Override
        protected void onPostExecute(RouteParameters params) {
            super.onPostExecute(params);
            if (params != null) {
                // 设置起点和终点(替换成你的实际点位)
                MapPoint start = new MapPoint(-118.2437, 34.0522, SpatialReferences.getWgs84());
                MapPoint end = new MapPoint(-118.2500, 34.0580, SpatialReferences.getWgs84());
                
                // 添加停靠点到参数
                params.setStops(new Stop[]{new Stop(start), new Stop(end)});
                
                // 启动路由计算任务
                new RouteCalculateTask().execute(routeTask, params);
            }
        }
    }.execute(routeTask);
}

// 计算路由的后台任务
private class RouteCalculateTask extends AsyncTask<Object, Void, RouteResult> {
    @Override
    protected RouteResult doInBackground(Object... objects) {
        RouteTask task = (RouteTask) objects[0];
        RouteParameters params = (RouteParameters) objects[1];
        
        try {
            // 执行路由计算,必须在后台线程
            return task.solveRoute(params);
        } catch (ArcGISRuntimeException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    protected void onPostExecute(RouteResult result) {
        super.onPostExecute(result);
        if (result != null && result.getRoutes().size() > 0) {
            // 主线程中处理路由结果,比如在地图上绘制路线
            Route route = result.getRoutes().get(0);
            Polyline routeLine = route.getRouteGeometry();
            
            // 创建路线图形并添加到地图(假设你已创建GraphicsOverlay)
            Graphic routeGraphic = new Graphic(routeLine, new SimpleLineSymbol(SimpleLineSymbol.Style.SOLID, Color.RED, 3));
            graphicsOverlay.getGraphics().add(routeGraphic);
        } else {
            Toast.makeText(RoutingActivity.this, "路由计算失败", Toast.LENGTH_SHORT).show();
        }
    }
}

4. 关键注意事项

  • 线程严格隔离:所有涉及Geodatabase、RouteTask的初始化和耗时操作,必须放在doInBackground中;UI更新(比如添加图形、提示)必须放在onPostExecute(主线程)。
  • 资源释放:使用完Geodatabase后记得调用close()方法,避免内存泄漏。
  • 权限配置:如果geodatabase在外部存储,确保App申请了READ_EXTERNAL_STORAGE权限;用内部存储(如示例中的getFilesDir())则无需额外权限。

三、其他排查方向

如果按上述步骤仍报错,检查以下几点:

  • 确认离线geodatabase中的网络数据集有效,可通过ArcGIS Pro打开验证。
  • 100.2.1版本的SDK集成是否正确,gradle依赖是否完整。
  • 不要在Application上下文或非UI线程中初始化MapView相关组件,MapView必须在Activity/Fragment的UI线程中创建。

内容的提问来源于stack exchange,提问作者user3176574

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:48:54