Я пытаюсь реализовать SDK автозаполнения поиска мест Google в моем приложении kotlin для Android.

Я использую второй метод, указанный в официальной документации:

Используйте намерение для запуска действия автозаполнения

Вот мой код:


    private  var fromLocation: LatLng? = LatLng(0.0, 0.0)
    private  var toLocation: LatLng? = LatLng(0.0, 0.0)


    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if (requestCode == AUTOCOMPLETE_REQUEST_CODE) {
            if (resultCode == RESULT_OK) {
                val place: Place? = data?.let { Autocomplete.getPlaceFromIntent(it) }
                if (PLACE_PICKING_MODE == 1) {
                    fromLocation = place?.latLng
                    val theIcon = R.drawable.gps_default
                    placeMarkerOnMap(fromLocation, theIcon)
                    map.animateCamera(CameraUpdateFactory.newLatLngZoom(fromLocation, 17f))
                } else if (PLACE_PICKING_MODE == 2) {
                    toLocation = place?.latLng
                    val theIcon = R.drawable.gps_default
                    placeMarkerOnMap(toLocation, theIcon)
                    map.animateCamera(CameraUpdateFactory.newLatLngZoom(toLocation, 17f))
                }
            } else if (resultCode == AutocompleteActivity.RESULT_ERROR) {
                // TODO: Handle the error.
                val status: Status = Autocomplete.getStatusFromIntent(data!!)
            } else if (resultCode == RESULT_CANCELED) {
                println("user Canceled")
            }
        }


        if (requestCode == REQUEST_CHECK_SETTINGS) {
            if (resultCode == Activity.RESULT_OK) {
                locationUpdateState = true
                startLocationUpdates()
            }
        }


    }

Каждый раз, в конце концов, это заканчивается ошибкой kotlin.KotlinNullPointerExceptio

ОБНОВЛЕНИЕ

На основе Дж. Дж. Якобса ответ, я изменил несколько строк внутри IF statements, чтобы они были такими:

                if (PLACE_PICKING_MODE == 1) {
                    if (place != null) {
                        fromLocation = place.latLng!!
                    }
                    val theIcon = R.drawable.gps_default
                    placeMarkerOnMap(fromLocation, theIcon)
                    map.animateCamera(CameraUpdateFactory.newLatLngZoom(fromLocation, 17f))
                } else if (PLACE_PICKING_MODE == 2) {
                    if (place != null) {
                        toLocation = place.latLng!!
                    }
                    val theIcon = R.drawable.gps_default
                    placeMarkerOnMap(toLocation, theIcon)
                    map.animateCamera(CameraUpdateFactory.newLatLngZoom(toLocation, 17f))
                }

Но все же это дает мне ошибку:

Failure delivering result ResultInfo{who=null, request=4, result=-1, data=Intent { (has extras) }} to activity {com.innoventiq.arkbeh/com.innoventiq.arkbeh.MainActivity}: kotlin.KotlinNullPointerException

И указал мне на эти строки:

fromLocation = place.latLng!!

А также

toLocation = place.latLng!!

0
Ahmed Wagdi 19 Окт 2019 в 14:56

1 ответ

Лучший ответ

Глядя на полученный код ошибки, он должен точно определить, какая строка вызывает NullPointerException.

Если data = null (поскольку он имеет тип Intent, допускающий значение NULL?), place также будет null (в этом случае блок data?.let{...} возвращает только null). Это вызывает проблемы в трех местах:

  1. В первом блоке if(PLACE_PICKING_MODE == 1) fromLocation теперь также будет null и ваш вызов placeMarkerOnMap со значением null для местоположения.
  2. Во втором блоке if та же проблема с toLocation
  3. При получении статуса из намерения, если data равно null, data!! выдает KotlinNullPointerException

Вероятно, вам просто нужно сделать еще несколько проверок null, прежде чем выполнять какую-либо условную логику.

РЕДАКТИРОВАТЬ

Хороший способ выполнить проверку null - это сделать что-то вроде следующего

val place: Place? = data?.let { Autocomplete.getPlaceFromIntent(it) }

if (requestCode == AUTOCOMPLETE_REQUEST_CODE) {
    if (resultCode == RESULT_OK) {
        val place: Place? = data?.let { Autocomplete.getPlaceFromIntent(it) }
        place?.let { //One time null-check for place
            if (PLACE_PICKING_MODE == 1) {
                fromLocation = it.latLng
                val theIcon = R.drawable.gps_default
                placeMarkerOnMap(fromLocation, theIcon)
                map.animateCamera(CameraUpdateFactory.
                    newLatLngZoom(fromLocation, 17f))
            } else if (PLACE_PICKING_MODE == 2) {
                toLocation = it.latLng
                val theIcon = R.drawable.gps_default
                placeMarkerOnMap(toLocation, theIcon)
                map.animateCamera(CameraUpdateFactory.
                    newLatLngZoom(toLocation, 17f))
            }
        }
    } else if (resultCode == AutocompleteActivity.RESULT_ERROR) {
        // TODO: Handle the error.
        val status: Status = Autocomplete.getStatusFromIntent(data!!)
    } else if (resultCode == RESULT_CANCELED) {
        println("user Canceled")
    }
}

Однако, если вы посмотрите документацию, которую вы связали в своем исходном вопросе, вы действительно можете избавиться от проверки data?.let{...}, потому что обычная функция фактически устанавливает данные как не допускающие значения NULL. Сигнатура функции

override fun onActivityResult(int requestCode, int resultCode, Intent data)

Фактически гарантирует, что намерение никогда не должно быть null, если вы не установите его на null в своем коде для ваших целей. Настоящая проблема должна заключаться в том, что place.latLng есть null и, вероятно, не должно быть. Но если это возможно в вашем последнем приложении, вам необходимо выполнить нулевую проверку и обработать ошибку.

1
JJ Jacobs 19 Окт 2019 в 17:25