HomeFragment:
Код: Выделить всё
@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()
)
}
}
Код: Выделить всё
@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 = getCurrentLocationUseCase()
private val _uiState = MutableStateFlow(HomeState())
val uiState: StateFlow = _uiState.asStateFlow()
private val _oneTimeEvent = MutableSharedFlow()
val oneTimeEvent: SharedFlow = _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 = repository.currentLocation
}
Код: Выделить всё
class LocationRepositoryImpl @Inject constructor(
private val deviceLocationProvider: DeviceLocationProvider
) : LocationRepository {
private val _currentLocation = MutableStateFlow(null)
override val currentLocation: StateFlow = _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"}")
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/790 ... pplication
Мобильная версия