无法在Android应用程序中正确初始化Mapbox

问题描述 投票:0回答:1

我尝试在我的应用程序中使用 Mapbox,但遇到一些问题。我的代码如下所示:

首页片段:

@AndroidEntryPoint
class HomeFragment : Fragment() {

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

   private lateinit var onBackPressedCallback: OnBackPressedCallback

   private val viewModel: HomeViewModel by viewModels()

   private lateinit var map: GoogleMap
   private lateinit var mapView: MapView
   private lateinit var locationComponentPlugin: LocationComponentPlugin

   private val markersManager = MarkersManager()
   private val routesManager = RoutesManager()

   private val onIndicatorBearingChangedListener = OnIndicatorBearingChangedListener {
        mapView.mapboxMap.setCamera(CameraOptions.Builder().bearing(it).build())
    }

    private val onIndicatorPositionChangedListener = OnIndicatorPositionChangedListener {
        mapView.mapboxMap.setCamera(CameraOptions.Builder().center(it).build())
        mapView.gestures.focalPoint = mapView.mapboxMap.pixelForCoordinate(it)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        MapboxOptions.accessToken = requireContext().getString(R.string.mapbox_access_token)
    }

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

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        setupMap()
        setupView()
        setupOnBackPress()
        setupViewModelSubscriptions()
    }

    override fun onResume() {
        super.onResume()

        val missingPermissions = PermissionUtils.checkPermissions(requireContext(), neededPermissions)
        if (missingPermissions.isNotEmpty()) {
            findNavController()
                .navigate(R.id.action_homeFragment_to_missingPermissionsFragment)
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        onBackPressedCallback.remove()
        _binding = null
    }

    private fun setupView() {
        binding.btnManageCars.setOnClickListener {
            findNavController().navigate(R.id.action_homeFragment_to_manageCarsFragment)
        }
        binding.btnPlaceCar.setOnClickListener {
            onPlaceClicked()
        }
        binding.btnStartNavi.setOnClickListener {
            viewModel.onEvent(HomeEvent.StartNavigation)
        }
        binding.btnCancelNavi.setOnClickListener {
            viewModel.onEvent(HomeEvent.CancelNavigation)
        }
    }

    private fun setupMap() {
        mapView = MapView(requireContext())
        mapView.mapboxMap.loadStyle(Style.STANDARD)
        initLocationComponent()
    }

    private fun initLocationComponent() {
        locationComponentPlugin = mapView.location
        locationComponentPlugin.updateSettings {
            puckBearing = PuckBearing.COURSE
            puckBearingEnabled = true
            enabled = true
            locationPuck = LocationPuck2D(
                bearingImage = ImageHolder.from(com.mapbox.maps.R.drawable.mapbox_user_puck_icon),
                shadowImage = ImageHolder.from(com.mapbox.maps.R.drawable.mapbox_user_icon_shadow),
                scaleExpression = interpolate {
                    linear()
                    zoom()
                    stop {
                        literal(0.0)
                        literal(0.6)
                    }
                    stop {
                        literal(20.0)
                        literal(1.0)
                    }
                }.toJson()
            )
        }  

        locationComponentPlugin.addOnIndicatorPositionChangedListener(onIndicatorPositionChangedListener)
        locationComponentPlugin.addOnIndicatorBearingChangedListener(onIndicatorBearingChangedListener)
    }

    private fun setupOnBackPress() {
        onBackPressedCallback = object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                this.isEnabled = false
                requireActivity().onBackPressedDispatcher.onBackPressed()
            }
        }

        requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, onBackPressedCallback)
    }

    private fun setupViewModelSubscriptions() {
        viewLifecycleOwner.lifecycleScope.launch {
            viewLifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
                launch {
                    viewModel.lastLocation.collectLatest { location ->
                        location?.let {
                            updateUserLocation(it)
                        }
                    }
                }
                launch {
                    viewModel.oneTimeEvent.collect { event ->
                        manageOneTimeEvent(event)
                }
            }
        }
    }

    private fun updateUserLocation(location: Location) {
        mapView.mapboxMap.setCamera(
            CameraOptions.Builder()
                .center(Point.fromLngLat(location.longitude, location.latitude))
                .zoom(25.0)
                .build()
        )
    }
}

HomeView模型:

@HiltViewModel
class HomeViewModel @Inject constructor(
    private val startLocationUpdatesUseCase: StartLocationUpdatesUseCase,
    private val stopLocationUpdatesUseCase: StopLocationUpdatesUseCase,
    private val getCurrentLocationUseCase: GetCurrentLocationUseCase,
    private val getAllCarsUseCase: GetAllCarsUseCase,
    private val getPlacedCarsUseCase: GetPlacedCarsUseCase,
    private val startNavigationUseCase: StartNavigationUseCase,
    private val setCarLocationUseCase: SetCarLocationUseCase,
    private val removeCarLocationUseCase: RemoveCarLocationUseCase,
) : ViewModel() {

    val lastLocation: StateFlow<Location?> = getCurrentLocationUseCase()

    private val _uiState = MutableStateFlow(HomeState())
    val uiState: StateFlow<HomeState> = _uiState.asStateFlow()

    private val _oneTimeEvent = MutableSharedFlow<HomeOneTimeEvent>()
    val oneTimeEvent: SharedFlow<HomeOneTimeEvent> = _oneTimeEvent.asSharedFlow()

    init {
        startLocationUpdatesUseCase()
        onEvent(HomeEvent.GetUserCars)
        onEvent(HomeEvent.GetPlacedCars)
    }
    ...
    ...
    ...
}

使用案例:

class StartLocationUpdatesUseCase@Inject constructor(
    private val repository: LocationRepository
) {

    operator fun invoke() {
        repository.startLocationUpdates()
    }

}

class StopLocationUpdatesUseCase @Inject constructor(
    private val repository: LocationRepository
) {

    operator fun invoke() = repository.stopLocationUpdates()

}

class GetCurrentLocationUseCase @Inject constructor(
    private val repository: LocationRepository
) {

    operator fun invoke(): StateFlow<Location?> = repository.currentLocation

}

存储库:

class LocationRepositoryImpl @Inject constructor(
    private val deviceLocationProvider: DeviceLocationProvider
) : LocationRepository {

     private val _currentLocation = MutableStateFlow<Location?>(null)
     override val currentLocation: StateFlow<Location?> = _currentLocation.asStateFlow()

    private val locationObserver = LocationObserver { locations ->
        _currentLocation.value = locations.lastOrNull()
    }

    override fun startLocationUpdates() {
        deviceLocationProvider.addLocationObserver(locationObserver)
    }

    override fun stopLocationUpdates() {
        deviceLocationProvider.removeLocationObserver(locationObserver)
    }
}

和定位模块

@Module
@InstallIn(SingletonComponent::class)
class LocationModule {

    @Provides
    fun provideDeviceLocationProvider(): DeviceLocationProvider {
        val locationService = LocationServiceFactory.getOrCreate()
        val request = LocationProviderRequest.Builder()
        .interval(IntervalSettings.Builder().interval(1000L).minimumInterval(1000L).maximumInterval(5000L).build())
            .displacement(0f)
            .accuracy(AccuracyLevel.HIGHEST)
            .build()

        val result = locationService.getDeviceLocationProvider(request)
        if (result.isValue) {
            return result.value!!
        } else {
            throw IllegalStateException("Cannot obtain DeviceLocationProvider: ${result.error?.message ?: "Unknown error"}")
        }
    }

}

由于某些未知原因,我无法在地图上看到用户,甚至无法在位置更新时更改相机。当前的行为是应用程序在启动时显示地图并且没有任何变化。我什至可以更改地图样式,但这也没有任何作用。有谁知道可能是什么问题?

android kotlin mapbox mapbox-android
1个回答
0
投票
    private fun setupMap() {
        mapView = MapView(requireContext())
        mapView.mapboxMap.loadStyle(Style.STANDARD)
        initLocationComponent()
    }

在这里,您正在创建一个

MapView
小部件,为其配置样式,然后将其丢弃。特别是,它没有出现在 UI 中,因为您没有执行任何操作将其放入 UI 中。

当前行为是应用程序在启动时显示地图

这意味着您在某个地方有另一个

MapView
,也许在
fragment_home.xml
中,您应该通过
FragmentHomeBinding
使用。因此,使用该
MapView
并删除您在
setupMap()
中创建的那个。

© www.soinside.com 2019 - 2024. All rights reserved.