由于使用 GPS 获取当前位置较晚导致应用程序崩溃

Posted

技术标签:

【中文标题】由于使用 GPS 获取当前位置较晚导致应用程序崩溃【英文标题】:App Crash due to lateinit of late getting current location with GPS 【发布时间】:2021-11-05 05:05:29 【问题描述】:

我正在尝试获取当前位置,但是应用程序崩溃是因为应用程序发现了 lateinit 属性尚未初始化,因为该应用程序尚未请求 GPS 的用户许可以获取当前位置。


下面是代码:

class FirstFragment : Fragment(), OnMapReadyCallback

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

    private lateinit var currentLocation: Location
    private lateinit var fusedLocationProvider: FusedLocationProviderClient
    private val permissionCode = 101

    private lateinit var googleMap: GoogleMap
    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.toString() + " "
                        + currentLocation.longitude.toString(), Toast.LENGTH_SHORT).show()

            
        
    


    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]))
        


    // Here is the problem
        val latLng = com.google.android.gms.maps.model.LatLng(currentLocation.latitude, currentLocation.longitude)
        val markerOptions = MarkerOptions().position(latLng).title("Current Location")
        googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 16.0f))
        googleMap.addMarker(markerOptions)

    

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) 
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when(requestCode)
            permissionCode -> if (grantResults.isEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)
                fetchLocation()
            
        
    

如何防止应用崩溃,或者让 onMapReady() 先等待用户的权限请求,然后再将当前位置标记放到地图上?


【问题讨论】:

此处 currentLocation 属性未初始化 【参考方案1】:

两件事

在这种情况下不要使用lateinit,因为您试图在获得无法保证您会得到的东西之前访问属性

改为可空

private var currentLocation: Location? = null

然后在访问它之前进行空检查

if(currentLocation != null)


第二次移动你在地图上放置地图标记的位置,而不是在onMapReady 中,你还应该让你的googleMap 属性为空,因为你可能会遇到接收到位置的情况在地图准备好之前,如果您已经有位置,您可以在 onMapReady 中设置位置,或者在获得位置时设置它,因为地图在您获得位置之前就已经准备好了

【讨论】:

你需要currentLocation?.let 之类的东西,或者在if语句之前加上val currentLocation = currentLocation,因为它是一个属性。

以上是关于由于使用 GPS 获取当前位置较晚导致应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

Android:如何使用 GPS 提供程序获取离线当前位置?

仅在单击按钮时获取当前 GPS 位置,然后停止使用 GPS

如何使用 Google App 或 GPS 获取当前位置? [复制]

如何获取当前 GPS 位置? (最后不知道)

如何使用 GPS 获取我在 Android 中的当前位置?

使用 GPS_PROVIDER 和 NETWORK_PROVIDER 获取当前位置的问题