简体   繁体   English

Kotlin - Here Maps - 从回调中获取地址 function

[英]Kotlin - Here Maps - Get address out of callback function

I am attempting to get the address out of the callback function.我试图从回调 function 中获取地址。 I have been reading the documentation for CallBacks and some posts but still don't get why this is not working, as at the moment of returning the 'address' variable the callback has already finished.我一直在阅读 CallBacks 的文档和一些帖子,但仍然不明白为什么这不起作用,因为在返回“地址”变量的那一刻,回调已经完成。

Thank you in advance!先感谢您!

    private fun getAddressForCoordinates(geoCoordinates: GeoCoordinates):String {
    address = "unchanged"
    val maxItems = 1
    val reverseGeocodingOptions = SearchOptions(LanguageCode.EN_GB, maxItems)
    searchEngine.search(geoCoordinates, reverseGeocodingOptions, addressSearchCallback)

    return address

}

private val addressSearchCallback =
    SearchCallback { searchError, list ->
        if (searchError != null) {
            //showDialog("Reverse geocoding", "Error: $searchError")
            Toast.makeText(context, "Error: $searchError", Toast.LENGTH_LONG).show()
            return@SearchCallback
        }

        Toast.makeText(
            context,
            "Reverse geocoded address:" + list!![0].address.addressText,
            Toast.LENGTH_LONG
        ).show()

        address = list[0].address.addressText
    }

From your code and comment I assume you are not familiar with the concept of asynchronous execution.从您的代码和评论中,我假设您不熟悉异步执行的概念。 That concept was well described here .这个概念在这里得到了很好的描述。 I'll quote the main point:我将引用主要观点:

When you execute something synchronously, you wait for it to finish before moving on to another task.当您同步执行某事时,您会等待它完成,然后再继续执行另一个任务。 When you execute something asynchronously, you can move on to another task before it finishes.当您异步执行某事时,您可以在它完成之前继续执行另一个任务。

The fact that search() requires providing a callback and it doesn't simply return search results, is a good indication that it is most probably asynchronous. search()需要提供回调并且它不简单地返回搜索结果这一事实很好地表明它很可能是异步的。 Invoking it is like saying: "Search for the data in the background and let me know when you have it. This is my email address - please send me my results there".调用它就像是在说:“在后台搜索数据,当你有数据时告诉我。这是我的 email 地址 - 请把我的结果发给我”。 Where email address is your callback.其中 email 地址是您的回调。 Invoking search() method does not block execution of your code, it does not wait for results - it only schedules searching and returns almost immediately.调用search()方法不会阻止代码的执行,它不会等待结果——它只会安排搜索并几乎立即返回。

Asynchronous processing is usually more tricky than a regular, synchronous code, but in many cases it is more efficient.异步处理通常比常规的同步代码更棘手,但在许多情况下它更有效。 In your case you can either try to "convert" original async API of the library to sync API that your code expects - but this is not recommended approach.在您的情况下,您可以尝试“转换”库的原始异步 API 以同步您的代码期望的 API - 但这不是推荐的方法。 Or you can redesign your code, so it will work asynchronously.或者你可以重新设计你的代码,让它异步工作。 For example, instead of doing this:例如,不要这样做:

fun yourMethodThatNeedsAddress() {
    val address = getAddressForCoordinates()
    doSomethingWithAddress(address)
}

You need to do this:你需要这样做:

fun yourMethodThatNeedsAddress() {
    scheduleGetAddressForCoordinates() // renamed getAddressForCoordinates()
}

fun addressSearchCallback() {
    ...
    doSomethingWithAddress(address)
}

So, whatever you planned to do with the acquired address, you can't do this straight after you started searching.因此,无论您计划对获取的地址做什么,都不能在开始搜索后立即执行此操作。 You need to wait for a callback and then continue with processing of your address from there.您需要等待回调,然后从那里继续处理您的地址。

The SearchEngine from the 4.x HERE SDK needs an online connection as it is fetching results from a remote backend. 4.x HERE SDK的搜索引擎需要在线连接,因为它正在从远程后端获取结果。 This may take a few milliseconds, depending on your network connection.这可能需要几毫秒,具体取决于您的网络连接。 So, whenever you perform a search request, you need to wait until the callback is called:因此,无论何时执行搜索请求,都需要等到回调被调用:

searchEngine.search(geoCoordinates, reverseGeocodingOptions, addressSearchCallback)

When you call this, you pass addressSearchCallback as parameter.当您调用它时,您将addressSearchCallback作为参数传递。 The implementation for addressSearchCallback can look like in your example. addressSearchCallback的实现可能类似于您的示例。 It will be called whenever the operation has finished.只要操作完成,就会调用它。 If the device is offline, then an error will be shown.如果设备处于离线状态,则会显示错误。

Note that the search() method is not returning any results immediately.请注意, search()方法不会立即返回任何结果。 These are passed to the callback, which happens asynchronously on a background thread.这些被传递给回调,该回调在后台线程上异步发生。 Thus, your application can continue to work without blocking any UI.因此,您的应用程序可以继续工作而不会阻塞任何 UI。

Once results are retrieved, the callback will be executed by the HERE SDK on the main thread.一旦检索到结果,回调将由主线程上的 HERE SDK 执行。

So, if your code needs to do something with the address result, you have to do it inside the onSearchCompleted() method defined by the SearchCallback .因此,如果您的代码需要对地址结果执行某些操作,您必须在SearchCallback定义的onSearchCompleted()方法中执行此操作。 If you write it in plain Java without lambda notation, it is more visible: You create a new SearchCallback object and pass it as parameter to the SearchEngine.如果你用普通的 Java 写它而不用 lambda 表示法,它会更明显:你创建一个新的SearchCallback object 并将其作为参数传递给 SearchEngine。 The SearchEngine stores the object and executes the object's onSearchCompleted() whenever it thinks it's the right time: SearchEngine 存储 object 并在认为合适的时间执行对象的onSearchCompleted()

private SearchCallback addressSearchCallback = new SearchCallback() {
    @Override
    public void onSearchCompleted(@Nullable SearchError searchError, @Nullable List<Place> list) {
        if (searchError != null) {
            showDialog("Reverse geocoding", "Error: " + searchError.toString());
            return;
        }

        // If error is null, list is guaranteed to be not empty.
        showDialog("Reverse geocoded address:", list.get(0).getAddress().addressText);

        // Here is the place to do something more useful with the Address object ...!
    }
};

I took this from this GitHub code snippet.我从这个GitHub 代码片段中获取了这个。 Note that there is also an OfflineSearchEngine , that works without an internet connection, but for some reason it follows the same pattern and executes the task asynchronously.请注意,还有一个OfflineSearchEngine ,它可以在没有互联网连接的情况下工作,但由于某种原因,它遵循相同的模式并异步执行任务。

private void getAddressForCoordinates(GeoCoordinates geoCoordinates) {
    int maxItems = 1;
    SearchOptions reverseGeocodingOptions = new SearchOptions(LanguageCode.EN_GB, maxItems);

    searchEngine.search(geoCoordinates, reverseGeocodingOptions, new SearchCallback() {
        @Override
        public void onSearchCompleted(@Nullable SearchError searchError, @Nullable List<Place> list) {
            if (searchError != null) {
                showDialog("Reverse geocoding", "Error: " + searchError.toString());
                return;
            }

            // If error is null, list is guaranteed to be not empty.
            showDialog("Reverse geocoded address:", list.get(0).getAddress().addressText);
        }
    });
}

SearchEngine, a SearchOptions instance needs to be provided to set the desired LanguageCode. SearchEngine,需要提供一个 SearchOptions 实例来设置所需的 LanguageCode。 It determines the language of the resulting address.它确定结果地址的语言。 Then we can make a call to the engine's search()-method to search online for the address of the passed coordinates.然后我们可以调用引擎的 search() 方法在线搜索传递的坐标的地址。 In case of errors, such as when the device is offline, SearchError holds the error cause.如果出现错误,例如设备离线时,SearchError 会保存错误原因。

The reverse geocoding response contains either an error or a result: SearchError and the result list can never be null at the same time - or non-null at the same time.反向地理编码响应包含错误或结果:SearchError 和结果列表永远不能同时是 null - 或同时非空。

The Address object contained inside each Place instance is a data class that contains multiple String fields describing the address of the raw location, such as country, city, street name, and many more.每个 Place 实例中包含的地址 object 是一个数据 class,其中包含描述原始位置地址的多个字符串字段,例如国家、城市、街道名称等等。 Consult the API Reference for more details.有关详细信息,请参阅 API 参考。 If you are only interested in receiving a readable address representation, you can access addressText, as shown in the above example.如果您只对接收可读的地址表示感兴趣,则可以访问 addressText,如上例所示。 This is a String containing the most relevant address details, including the place's title.这是一个字符串,其中包含最相关的地址详细信息,包括地点的标题。

Please refer to following link for detailed documentation on search() function and parameters associated with it.有关 search() function 及其相关参数的详细文档,请参阅以下链接。

https://developer.here.com/documentation/android-sdk-explore/4.4.0.2/dev_guide/topics/search.html https://developer.here.com/documentation/android-sdk-explore/4.4.0.2/dev_guide/topics/search.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM