简体   繁体   English

当我想从当前片段返回 go 时出现“未附加到上下文”错误

[英]I get "not attached to a context" error when I want to go back from current fragment

This code belongs to a fragment which shows the user's current location.After getting location when I want to go back to previous fragment App crashes.Logcat says error is happening here: "val geocoder = Geocoder(requireContext(), Locale.getDefault())" If anyone could assist me, I would greatly appreciate it此代码属于显示用户当前位置的片段。当我想 go 返回上一个片段时获取位置后应用程序崩溃。Logcat 说这里发生错误:“val 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()
}

} }

I used 'requireActivity' instead of 'requireContext' but didn't work我使用了“requireActivity”而不是“requireContext”,但没有用

As you said, beacuse the crash happens when you go back to the previous fragment, probably the locationCallback getting called when the current fragment is detached from the activity.正如您所说,因为崩溃发生在您 go 回到前一个片段时,可能是在当前片段与活动分离时调用了 locationCallback。 Inside the updateAddressUI you are getting the context in that momment when your view is detached.在 updateAddressUI 中,当您的视图分离时,您将获得那个时刻的上下文。

If is ok with your logic you can keep the context reference inside the callBack object and work with this.如果您的逻辑没问题,您可以将上下文引用保留在回调 object 中并使用它。

Try to change the locationCallback to and pass the context to the updateAddressUI function.尝试将 locationCallback 更改为并将上下文传递给 updateAddressUI function。

private var locationCallback = object : LocationCallback() {

    val context = requireContext()

    override fun onLocationResult(p0: LocationResult) {

        val location: Location? = p0.lastLocation

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


        }

    }
}

Change also the updateAddressUI function like this.像这样更改 updateAddressUI function。

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


}

I changed the code in this way:我以这种方式更改了代码:

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

in this methode:在这个方法中:

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
        }

暂无
暂无

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

相关问题 我得到片段未附加到上下文。 需要使用什么上下文? - I get Fragment not attached to a context. What context need to use? 当召回方法Fragment没有附加到上下文错误时。 我应该发送和接收什么背景? - When recall methods Fragment not attached to a context Error. What context should i send and receive? 当我 go 从片段 A 到 B 然后从片段 B 回到 A 时,如何避免重新创建片段 A - How to avoid re-creation of fragment A when i go from fragment A to B and then back from fragment B to A 当我单击工具栏后按时,我如何 go 从片段 B 回到 A? - How can i go back to A from fragment B when I click on the toolbar back press? 当我离开片段并再次输入时,错误片段未附加到活动 - Error Fragment not attached to an activity when I leave a fragment and enter it again 我如何从片段2返回片段1? 如图所示 - How can I go back from fragment 2 to fragment 1 ? as shown in the picture 从片段A-&gt;片段B-&gt;片段C传输数据。当用户单击“后退”按钮时,我想返回片段A和数据 - transfer data from fragment A -> fragment B - > fragment C. When user click Back button, I want to return to fragment A and data 当我回到 Fragment 时,立即调用观察者 - When I go back to a Fragment the observer is immediately called 如何从Android中的当前片段返回上一个片段 - How to go back to previous fragment from current fragment in android 如何从片段返回主要活动 - How can I go back to main activity from a Fragment
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM