【ArcGIS Runtime SDK for Android-09】Loadable pattern for asynchronous resources

时间:2019-01-31
本文章向大家介绍【ArcGIS Runtime SDK for Android-09】Loadable pattern for asynchronous resources,主要包括【ArcGIS Runtime SDK for Android-09】Loadable pattern for asynchronous resources使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

图层(layers)、地图(maps)、门户项(portal items)、任务(tasks)等资源通常依赖于磁盘上的远程服务或数据集来初始化它们的状态。访问这些数据的本质要求资源异步地初始化它们的状态。可加载设计模式(The loadable design patter)统一了不同资源用于异步加载元数据( metadata)的行为,采用此模式的资源称为“可加载”。该模式还提供了一种机制,可以在以前的加载尝试失败时重试,以便您能够正确地处理和从异常情况(如网络中断或服务中断)中恢复。可加载资源( loadable resources)适当地处理要加载的并发和重复请求,以适应在应用程序的各个部分之间共享同一资源实例的常见做法,并允许取消,以便您可以取消加载资源,例如,如果服务响应缓慢。最后,可加载资源通过可检查(inspected )和监视(monitored)的显式状态提供关于其初始化状态的信息。

1、Loadable API

符合可加载模式的类实现Loadable 接口。

(1)Load status

getLoadStatus方法返回可加载资源的状态。可能有四种状态。

  • NOT_LOADED—资源没有被要求加载它的元数据,它的状态还没有正确初始化。
  • LOADING——资源正在异步加载其元数据的过程中。
  • FAILED_TO_LOAD—资源未能加载其元数据(例如,由于网络中断,或操作被取消,等等)。遇到的错误可以从getLoadError方法中获得。
  • LOADED——资源成功加载其元数据,并正确初始化其状态。

以下状态转换表示可加载资源经过的阶段。

Loadable接口包含监听器,可以方便地监视可加载资源的状态、显示进度以及在状态发生变化时采取行动。

(2)Loading

当调用loadAsync时,资源开始异步加载其元数据。此时,load状态将从NOT_LOADED更改为LOADING。当异步操作完成时,将调用回调。如果操作遇到错误,将填充回调中的错误参数,并将load状态设置为FAILED_TO_LOAD。如果操作成功完成,则错误参数为null,并将load状态设置为LOADED,这意味着资源已经完成了元数据的加载,现在已经正确地初始化了。

很多时候,相同的资源实例由应用程序的不同部分共享。例如,一个图例(legend)组件和一个目录组件( a table of contents component)可能访问同一层,它们都可能希望访问该图层的属性来填充它们的UI。或者可以在整个应用程序中共享相同的门户实例(portal instance),以在应用程序的不同部分显示用户的项(items)和组(groups)。为了适应这种类型的应用程序开发模式,并使事情变得简单,loadAsync支持多个“侦听器”。可以并发地反复调用它,但只尝试一次加载元数据。如果在调用loadAsync时,加载操作已经在进行中(LOADING状态),那么它只需在未完成的操作上进行回滚,并在该操作完成时排队调用回调。如果在调用loadAsync时操作已经完成(LOADED或FAILED_TO_LOAD 状态),则回调将立即使用操作的过去结果调用,无论成功还是失败,并且状态保持不变。这使得您可以安全地在可加载资源上自由调用loadAsync,而不必检查资源是否已加载,也不必担心每次都会发出不必要的网络请求。

如果资源未能加载,则随后对其调用loadAsync将不会更改其状态。回调函数将在出现过去的加载错误时立即调用。为了重试加载资源,必须使用retryLoadAsync。这种方法的优点是,如果,假设,loadAsync重试加载失败的资源,应用程序可以很容易地最终让许多异步请求加载相同的资源仅仅因为它共享相同的资源实例在应用程序的不同部分,每一部分试图加载资源没有首先检查是否已经加载。此模式允许不加区分地调用loadAsync,而不必担心会增加开销,并使用retryLoadAsync使重试成为一个单独的显式场景。

(3)Retry loading

当retryLoadAsync被调用时,资源会重试加载它的元数据,但只有在它之前加载失败(FAILED_TO_LOAD状态)或一开始没有加载(NOT_LOADED状态)的情况下。资源转换到加载状态,并重新尝试获取其元数据。在异步操作完成时调用回调。

如果资源已经获取了它的元数据并初始化了它的状态(LOADED状态),重试不会做任何事情。相反,重试会立即用过去的结果调用回调,对象的状态保持不变。不再获取对象的元数据。

如果在调用retryLoadAsync时,异步操作已经在进行中(LOADING状态),那么它只需在未完成的操作上进行回调,并在该操作完成时排队调用回调。

此方法的主要用例是,如果可加载项先前未能加载,例如,由于网络中断或服务中断。它不打算刷新已加载资源的元数据,而应该通过创建可加载资源的新实例来完成。

(4)Cancel loading

当cancelLoad被调用时,资源会取消任何未完成的异步操作来加载其元数据,并从LOADING转换到FAILED_TO_LOAD状态。getLoadError方法将返回反映该操作已被取消的信息。

应该谨慎使用此方法,因为该资源实例的所有排队回调都会被调用,并带有一个错误,表明操作已被取消。因此,应用程序中的一个组件可以在共享相同的资源实例时取消由其他组件发起的负载。

如果资源不在加载状态,cancelLoad方法什么也不做。

2、Conveniences

(1)Cascading load dependencies

可加载资源通常依赖于加载其他可加载资源来正确初始化其状态。例如,门户项在其父门户完成加载之前不能完成加载。在首次加载要素服务表之前,不能加载要素图层。这种情况称为负载依赖性。

通过依赖关系图在任何资源上透明地级联调用的可加载操作。这有助于简化可加载资源的使用,并将正确建立和管理其负载依赖关系的责任推给资源。

下面的代码示例展示了这种级联行为如何生成简洁的代码。加载地图会导致门户项开始加载,然后门户项开始加载门户。您不必显式地加载它们中的每一个。

// create a Map which is loaded from a webmap
UserCredential creds = new UserCredential("myuser", "password");
Portal portal = new Portal("http://myportal/");
portal.setCredential(creds);
final PortalItem portalItem = new PortalItem(portal, "5cdcac1d6d814b82a48453d3e3876fd1");


// make a map from portal item
map = new ArcGISMap(portalItem);


//load the map
map.loadAsync();


//listen to when it is loaded
map.addDoneLoadingListener(() -> {
  System.out.println("map loaded");
});

依赖项可能无法加载。一些依赖关系可能非常重要,如果没有这些依赖关系,初始化资源就无法成功加载,例如门户项对其门户的依赖关系。如果在加载此类依赖项时遇到故障,则该错误将冒泡到启动加载循环的资源,该资源也将无法加载。此外,重试加载该资源将自动重试加载失败的依赖项。其他的负载依赖关系可能是偶然的,例如地图对其中一个操作层的依赖关系,即使其中一个依赖关系无法加载,资源也可能能够成功加载。

(2)Overriding state before initialization

可加载资源的状态在完成加载之前不会正确初始化。在加载资源之前访问资源的属性可能返回空值或未初始化的值,这些值可能在资源加载完成时发生更改。因此,在访问资源的属性之前,始终建议等待资源完成加载。然而,很多时候,特别是在原型化过程中,您可能希望在加载资源之前更改属性值,而不考虑其正确的初始化值。例如,您可能希望更改图层的比例可见性或地图的初始视图。要简化此工作流而不要求首先加载资源,可加载资源允许在资源完成加载之前覆盖其属性,且被覆盖的值将优先于资源元数据中指定的值。

下面的代码示例展示了如何在不首先加载层的情况下覆盖该层的最小/最大缩放属性。

ArcGISMapImageLayer censusLayer =
  new ArcGISMapImageLayer("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer");
censusLayer.setMinScale(5000);
censusLayer.setMaxScale(1000000);


censusLayer.loadAsync();
censusLayer.addDoneLoadingListener(() -> {


  // overridden min & max scale values will be retained even when the resource finishes loading
  System.out.println("Layer Status: " + censusLayer.getLoadStatus());
  System.out.println("Min Scale: " + censusLayer.getMinScale() + " Max Scale: " + censusLayer.getMaxScale());
});

参考链接:

https://developers.arcgis.com/android/latest/guide/loadable-pattern.htm