kotlin 当我想从当前片段返回时,收到“未附加到上下文”错误

hivapdat  于 2023-01-31  发布在  Kotlin
关注(0)|答案(2)|浏览(130)

此代码属于显示用户当前位置的片段。获取位置后,当我想返回到以前的片段时,应用程序崩溃。Logcat显示错误发生在此处:“瓦尔geocoder = Geocoder(requireContext(),Locale.getDefault())”如果有人能帮助我,我将不胜感激

class LocationFragment : DialogFragment(), OnMapReadyCallback {

lateinit var binding: FragmentLocationBinding
private lateinit var map: GoogleMap

private val REQUEST_LOCATION_PERMISSION = 1
var lat: Double = 0.0
var long: Double = 0.0

private lateinit var fusedLocationProviderClient: FusedLocationProviderClient

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View {
    binding = FragmentLocationBinding.inflate(inflater, container, false)
    return binding.root
}


override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    val policy = StrictMode.ThreadPolicy.Builder().permitAll().build()
    StrictMode.setThreadPolicy(policy)

    fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(requireContext())
    enableMyLocation()
    binding.apply {
        prgBar.visibility=View.VISIBLE
        btnSaveLocation.setOnClickListener {
            dismiss()
        }
        val mapFragment = childFragmentManager
            .findFragmentById(R.id.map) as SupportMapFragment
        mapFragment.getMapAsync(this@LocationFragment)
    }
}

override fun onStart() {
    super.onStart()
    val dialog: Dialog? = dialog
    if (dialog != null) {
        dialog.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
        //dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
    }
}

override fun onMapReady(p0: GoogleMap) {
    map = p0
}

private fun isPermissionGranted(): Boolean {
    return ContextCompat.checkSelfPermission(
        requireContext(),
        Manifest.permission.ACCESS_FINE_LOCATION
    ) == PackageManager.PERMISSION_GRANTED
}

@SuppressLint("VisibleForTests")
private fun checkDeviceLocationSettings(resolve: Boolean = true) {
    val locationRequest = LocationRequest.create().apply {
        priority = LocationRequest.PRIORITY_LOW_POWER
    }
    val requestBuilder = LocationSettingsRequest.Builder().addLocationRequest(locationRequest)
    val settingsClient = LocationServices.getSettingsClient(requireActivity())
    val locationSettingsResponseTask =
        settingsClient.checkLocationSettings(requestBuilder.build())
    locationSettingsResponseTask.addOnFailureListener { exception ->
        if (exception is ResolvableApiException && resolve) {
            try {
                exception.startResolutionForResult(
                    requireActivity(),
                    REQUEST_TURN_DEVICE_LOCATION_ON
                )
            } catch (sendEx: IntentSender.SendIntentException) {
                Log.d(TAG, "Error getting location settings resolution: " + sendEx.message)
            }
        } else {
            Snackbar.make(
                binding.root,
                R.string.location_required_error, Snackbar.LENGTH_INDEFINITE
            ).setAction(android.R.string.ok) {
                checkDeviceLocationSettings()
            }.show()
        }

    }
}

@TargetApi(Build.VERSION_CODES.Q)
private fun requestQPermission() {
    val hasForegroundPermission = ActivityCompat.checkSelfPermission(
        requireContext(),
        Manifest.permission.ACCESS_FINE_LOCATION
    ) == PackageManager.PERMISSION_GRANTED

    if (hasForegroundPermission) {
        val hasBackgroundPermission = ActivityCompat.checkSelfPermission(
            requireContext(),
            Manifest.permission.ACCESS_BACKGROUND_LOCATION
        ) == PackageManager.PERMISSION_GRANTED
        if (hasBackgroundPermission) {
            checkDeviceLocationSettings()
        } else {
            ActivityCompat.requestPermissions(
                requireActivity(),
                arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION),
                REQUEST_CODE_BACKGROUND
            )
        }
    }
}

private fun enableMyLocation() {
    if (isPermissionGranted()) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            checkDeviceLocationSettings()
        } else {
            requestQPermission()
        }

        updateLocation()

    } else {
        ActivityCompat.requestPermissions(
            context as Activity,
            arrayOf<String>(Manifest.permission.ACCESS_FINE_LOCATION),
            REQUEST_LOCATION_PERMISSION
        )
    }
}

private fun updateLocation() {
    if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION)
        != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission
            (requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION)
        != PackageManager.PERMISSION_GRANTED
    ) {
        return
    }
    fusedLocationProviderClient.requestLocationUpdates(
        locationRequest(), locationCallback,
        Looper.myLooper()
    )
}

private fun locationRequest(): LocationRequest {
    return LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 3000)
        .setWaitForAccurateLocation(false)
        .setMinUpdateIntervalMillis(5000)
        .setMaxUpdateDelayMillis(5000)
        .build()
}

private var locationCallback = object : LocationCallback() {
    override fun onLocationResult(p0: LocationResult) {

        val location: Location? = p0.lastLocation

        if (location != null) {
            updateAddressUI(location)

        }

    }
}

@SuppressLint("MissingPermission")
fun updateAddressUI(location: Location) {
    map.isMyLocationEnabled = true
    val addressList: ArrayList<Address>
    val geocoder = Geocoder(requireContext(), Locale.getDefault())   //Getting error here
    addressList = geocoder.getFromLocation(
        location.latitude,
        location.longitude,
        1
    ) as ArrayList<Address>
    lat = addressList[0].latitude
    long = addressList[0].longitude

    binding.prgBar.visibility=View.INVISIBLE

    Toast.makeText(requireContext(), "$lat \n $long", Toast.LENGTH_SHORT).show()

    val latLng = LatLng(lat, long)
    val markerOptions = MarkerOptions().position(latLng).title("I am here!")
    map.animateCamera(CameraUpdateFactory.newLatLng(latLng))
    map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15f))
    map.addMarker(markerOptions)?.setIcon(bitmapFromVector(requireContext(),R.drawable.baseline_emoji_people_24))

}

private fun bitmapFromVector(context: Context, vectorResId: Int): BitmapDescriptor? {
    val vectorDrawable = ContextCompat.getDrawable(context, vectorResId)
    vectorDrawable!!.setBounds(0, 0, vectorDrawable.intrinsicWidth, vectorDrawable.intrinsicHeight)
    val bitmap = Bitmap.createBitmap(vectorDrawable.intrinsicWidth, vectorDrawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(bitmap)
    vectorDrawable.draw(canvas)
    return BitmapDescriptorFactory.fromBitmap(bitmap)
}

override fun onResume() {
    super.onResume()
    enableMyLocation()
}

}
我使用了“requireActivity”而不是“requireContext”,但不起作用

kwvwclae

kwvwclae1#

正如您所说,因为当您返回到上一个片段时会发生崩溃,可能是当前片段从Activity分离时调用了locationCallback。在updateAddressUI中,您将获得视图分离时的上下文。
如果您的逻辑没有问题,您可以将上下文引用保留在callBack对象中并使用它。
尝试将locationCallback更改为并将上下文传递给updateAddressUI函数。

private var locationCallback = object : LocationCallback() {

    val context = requireContext()

    override fun onLocationResult(p0: LocationResult) {

        val location: Location? = p0.lastLocation

        if (location != null) {
            updateAddressUI(location, context)

        }

    }
}

还可以像这样更改updateAddressUI函数。

@SuppressLint("MissingPermission")
fun updateAddressUI(location: Location, context: Context) {
    map.isMyLocationEnabled = true
    val addressList: ArrayList<Address>
    val geocoder = Geocoder(context, Locale.getDefault())   //Getting error here
    addressList = geocoder.getFromLocation(
        location.latitude,
        location.longitude,
        1
    ) as ArrayList<Address>
    lat = addressList[0].latitude
    long = addressList[0].longitude

    binding.prgBar.visibility=View.INVISIBLE

    Toast.makeText(context, "$lat \n $long", Toast.LENGTH_SHORT).show()

    val latLng = LatLng(lat, long)
    val markerOptions = MarkerOptions().position(latLng).title("I am here!")
    map.animateCamera(CameraUpdateFactory.newLatLng(latLng))
    map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15f))
    map.addMarker(markerOptions)?.setIcon(bitmapFromVector(context,R.drawable.baseline_emoji_people_24))

}
rur96b6h

rur96b6h2#

我这样修改了代码:

val geocoder = context?.let { Geocoder(it, Locale.getDefault()) }

在该方法中:

fun updateAddressUI(location: Location) {
        map.isMyLocationEnabled = true
        val addressList: ArrayList<Address>
        val geocoder = context?.let { Geocoder(it, Locale.getDefault()) }
        if (geocoder != null) {
            addressList = geocoder.getFromLocation(
                location.latitude,
                location.longitude,
                1
            ) as ArrayList<Address>
            lat = addressList[0].latitude
            long = addressList[0].longitude
        }

相关问题