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

Android获取GPS当前位置时lateinit未初始化导致应用崩溃如何解决

问题根源

  • onMapReady 方法和权限申请、位置获取的逻辑是异步执行的,大概率会在用户完成权限授权、拿到定位结果前就执行完成,此时lateinit修饰的currentLocation还未初始化,直接访问就会触发崩溃
  • 权限申请回调的判断逻辑存在错误,原逻辑grantResults.isEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED永远无法成立,空数组访问下标0会直接触发越界崩溃

解决方案

步骤1:修改定位变量定义,避免未初始化访问

将lateinit修饰的currentLocation改为可空类型,从根源避免未初始化访问异常:

// 替换原 private lateinit var currentLocation: Location
private var currentLocation: Location? = null

步骤2:抽离添加当前位置标记的逻辑

单独封装添加当前位置标记的方法,只有当定位结果和地图实例都准备完成时再调用:

private fun addCurrentLocationMarker() {
    // 双重校验,地图和定位都就绪才执行逻辑
    val map = googleMap ?: return
    val location = currentLocation ?: return

    val latLng = com.google.android.gms.maps.model.LatLng(location.latitude, location.longitude)
    val markerOptions = MarkerOptions().position(latLng).title("Current Location")
    map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 16.0f))
    map.addMarker(markerOptions)
}

步骤3:修改onMapReady逻辑,移除直接访问currentLocation的代码

onMapReady中只保留添加预置标记的逻辑,不要直接操作定位相关内容:

override fun onMapReady(map: GoogleMap) {
    googleMap = map
    for(i in locationArrayList!!.indices){
        googleMap.addMarker(MarkerOptions().position(locationArrayList!![i]).title("Marker $i"))
        googleMap.animateCamera(CameraUpdateFactory.zoomTo(18.0f))
        googleMap.moveCamera(CameraUpdateFactory.newLatLng(locationArrayList!![i]))
    }
    // 尝试添加当前位置标记,如果此时定位已经拿到就会直接添加,没拿到就什么都不做
    addCurrentLocationMarker()
}

步骤4:修改定位成功回调逻辑,拿到定位后主动触发添加标记

在fetchLocation的定位成功回调中,调用封装好的添加标记方法:

private fun fetchLocation(){
    if (ActivityCompat.checkSelfPermission(requireContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
        && ActivityCompat.checkSelfPermission(requireContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
    {
        ActivityCompat.requestPermissions(requireActivity(), arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), permissionCode)
        return
    }

    val task = fusedLocationProvider.lastLocation
    task.addOnSuccessListener { location ->
        if(location != null){
            currentLocation = location
            Toast.makeText(this.context, currentLocation.latitude.toString() + " "
                    + currentLocation.longitude.toString(), Toast.LENGTH_SHORT).show()
            // 拿到定位后调用添加标记方法
            addCurrentLocationMarker()
        }
    }
}

步骤5:修复权限申请回调的逻辑错误

修正权限判断条件,避免越界崩溃:

override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    when(requestCode){
        permissionCode -> if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED){
            fetchLocation()
        } else {
            // 可以在这里添加权限拒绝的提示逻辑
            Toast.makeText(requireContext(), "需要定位权限才能显示当前位置", Toast.LENGTH_SHORT).show()
        }
    }
}

完整修改后代码

class FirstFragment : Fragment(), OnMapReadyCallback{

    private var _binding: FragmentFirstBinding? = null
    private val binding get() = _binding!!

    // 修改为可空类型
    private var currentLocation: Location? = null
    private lateinit var fusedLocationProvider: FusedLocationProviderClient
    private val permissionCode = 101

    private var googleMap: GoogleMap? = null
    private val MasjidZahir = com.google.android.gms.maps.model.LatLng(6.1046784,100.3716608)
    private val Jabil = com.google.android.gms.maps.model.LatLng(5.3267065,100.2820637)
    private val TARUCKL = com.google.android.gms.maps.model.LatLng(3.2162302,101.7267724)
    private val TARUCPG = com.google.android.gms.maps.model.LatLng(5.4532105,100.2826858)
    private val MARINA = com.google.android.gms.maps.model.LatLng(1.3149938,103.890498)

    private var locationArrayList: ArrayList<com.google.android.gms.maps.model.LatLng>? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        fusedLocationProvider = LocationServices.getFusedLocationProviderClient(requireActivity())
        fetchLocation()
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        val map = binding.mapView
        mapView.onCreate(savedInstanceState)
        mapView.onResume()
        mapView.getMapAsync(this)
        locationArrayList = ArrayList()
        locationArrayList!!.add(MasjidZahir)
        locationArrayList!!.add(Jabil)
        locationArrayList!!.add(TARUCKL)
        locationArrayList!!.add(TARUCPG)
        locationArrayList!!.add(MARINA)
    }

    private fun fetchLocation(){
        if (ActivityCompat.checkSelfPermission(requireContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(requireContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
        {
            ActivityCompat.requestPermissions(requireActivity(), arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), permissionCode)
            return
        }
        val task = fusedLocationProvider.lastLocation
        task.addOnSuccessListener { location ->
            if(location != null){
                currentLocation = location
                Toast.makeText(this.context, "${currentLocation.latitude} ${currentLocation.longitude}", Toast.LENGTH_SHORT).show()
                addCurrentLocationMarker()
            }
        }
    }

    private fun addCurrentLocationMarker() {
        val map = googleMap ?: return
        val location = currentLocation ?: return
        val latLng = com.google.android.gms.maps.model.LatLng(location.latitude, location.longitude)
        val markerOptions = MarkerOptions().position(latLng).title("Current Location")
        map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 16.0f))
        map.addMarker(markerOptions)
    }

    override fun onMapReady(map: GoogleMap) {
        googleMap = map
        for(i in locationArrayList!!.indices){
            googleMap.addMarker(MarkerOptions().position(locationArrayList!![i]).title("Marker $i"))
            googleMap.animateCamera(CameraUpdateFactory.zoomTo(18.0f))
            googleMap.moveCamera(CameraUpdateFactory.newLatLng(locationArrayList!![i]))
        }
        addCurrentLocationMarker()
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when(requestCode){
            permissionCode -> if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED){
                fetchLocation()
            } else {
                Toast.makeText(requireContext(), "需要定位权限才能显示当前位置", Toast.LENGTH_SHORT).show()
            }
        }
    }
    
    // 补充销毁时清理binding避免内存泄漏
    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 23:39:02