diff --git a/data/src/main/java/com/stop/data/di/NetworkModule.kt b/data/src/main/java/com/stop/data/di/NetworkModule.kt index 3c49d978..3ef160ab 100644 --- a/data/src/main/java/com/stop/data/di/NetworkModule.kt +++ b/data/src/main/java/com/stop/data/di/NetworkModule.kt @@ -20,6 +20,7 @@ import okhttp3.Response import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit import retrofit2.converter.moshi.MoshiConverterFactory +import java.util.concurrent.TimeUnit import javax.inject.Named import javax.inject.Singleton @@ -40,6 +41,9 @@ internal object NetworkModule { loggingInterceptor: HttpLoggingInterceptor, ): OkHttpClient { return OkHttpClient.Builder() + .connectTimeout(5, TimeUnit.SECONDS) + .writeTimeout(5, TimeUnit.SECONDS) + .readTimeout(5, TimeUnit.SECONDS) .addInterceptor(loggingInterceptor) .addInterceptor(customInterceptor) .build() diff --git a/domain/src/main/java/com/stop/domain/usecase/route/GetLastTransportTimeUseCaseImpl.kt b/domain/src/main/java/com/stop/domain/usecase/route/GetLastTransportTimeUseCaseImpl.kt index 5e75c9e4..8d622946 100644 --- a/domain/src/main/java/com/stop/domain/usecase/route/GetLastTransportTimeUseCaseImpl.kt +++ b/domain/src/main/java/com/stop/domain/usecase/route/GetLastTransportTimeUseCaseImpl.kt @@ -378,7 +378,7 @@ internal class GetLastTransportTimeUseCaseImpl @Inject constructor( lastTime += TIME_CORRECTION_VALUE } - val lastTimeString = lastTime.toString().chunked(2).joinToString(":") + val lastTimeString = lastTime.toString().padStart(6, '0').chunked(2).joinToString(":") return TransportLastTime( transportMoveType = TransportMoveType.BUS, @@ -521,7 +521,7 @@ internal class GetLastTransportTimeUseCaseImpl @Inject constructor( lastTime += TIME_CORRECTION_VALUE } - val lastTimeString = lastTime.toString().chunked(2).joinToString(":") + val lastTimeString = lastTime.toString().padStart(6, '0').chunked(2).joinToString(":") return TransportLastTime( transportMoveType = TransportMoveType.BUS, diff --git a/presentation/src/main/java/com/stop/model/ErrorType.kt b/presentation/src/main/java/com/stop/model/ErrorType.kt index e84bf9aa..4582e909 100644 --- a/presentation/src/main/java/com/stop/model/ErrorType.kt +++ b/presentation/src/main/java/com/stop/model/ErrorType.kt @@ -12,4 +12,7 @@ enum class ErrorType(val stringResourcesId: Int) { AVAILABLE_BUS_NO_EXIST_YET(R.string.available_bus_no_exist_yet), BUS_DISAPPEAR_SUDDENLY(R.string.bus_disappear_suddenly), MISSION_SOMETHING_WRONG(R.string.mission_something_wrong), + SOCKET_TIMEOUT_EXCEPTION(R.string.socket_timeout_exception_please_retry), + UNKNOWN_EXCEPTION(R.string.unknown_exception_occur), + UNKNOWN_HOST_EXCEPTION(R.string.unknown_host_exception_occur), } \ No newline at end of file diff --git a/presentation/src/main/java/com/stop/ui/alarmsetting/AlarmSettingFragment.kt b/presentation/src/main/java/com/stop/ui/alarmsetting/AlarmSettingFragment.kt index af6894ee..268d6cef 100644 --- a/presentation/src/main/java/com/stop/ui/alarmsetting/AlarmSettingFragment.kt +++ b/presentation/src/main/java/com/stop/ui/alarmsetting/AlarmSettingFragment.kt @@ -111,8 +111,7 @@ class AlarmSettingFragment : Fragment() { //alarmSettingViewModel.makeAlarmWorker(transportLastTime.timeToBoard) val navController = findNavController() - navController.setGraph(R.navigation.nav_graph) - navController.popBackStack(R.id.action_global_mapFragment, false) + navController.popBackStack(R.id.mapFragment, false) requireActivity().viewModelStore.clear() } diff --git a/presentation/src/main/java/com/stop/ui/map/MapFragment.kt b/presentation/src/main/java/com/stop/ui/map/MapFragment.kt index 0279aa15..4549d4d3 100644 --- a/presentation/src/main/java/com/stop/ui/map/MapFragment.kt +++ b/presentation/src/main/java/com/stop/ui/map/MapFragment.kt @@ -11,6 +11,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels @@ -22,7 +23,6 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior import com.skt.tmap.TMapPoint import com.stop.AlarmActivity import com.stop.R -import com.stop.RouteNavGraphDirections import com.stop.alarm.SoundService import com.stop.databinding.FragmentMapBinding import com.stop.model.AlarmStatus @@ -141,24 +141,14 @@ class MapFragment : Fragment(), MapHandler { binding.homePanel.viewPanelStart.setOnClickListener { placeSearchViewModel.setPanelVisibility(View.INVISIBLE) - findNavController().apply { - setGraph(R.navigation.route_nav_graph) - navigate( - RouteNavGraphDirections.actionGlobalRouteFragment() - .setStart(placeSearchViewModel.panelInfo) - ) - } + val bundle = bundleOf("start" to placeSearchViewModel.panelInfo) + findNavController().navigate(R.id.action_mapFragment_to_route_nav_graph, bundle) } binding.homePanel.viewPanelEnd.setOnClickListener { placeSearchViewModel.setPanelVisibility(View.INVISIBLE) - findNavController().apply { - setGraph(R.navigation.route_nav_graph) - navigate( - RouteNavGraphDirections.actionGlobalRouteFragment() - .setEnd(placeSearchViewModel.panelInfo) - ) - } + val bundle = bundleOf("end" to placeSearchViewModel.panelInfo) + findNavController().navigate(R.id.action_mapFragment_to_route_nav_graph, bundle) } } diff --git a/presentation/src/main/java/com/stop/ui/route/RouteFragment.kt b/presentation/src/main/java/com/stop/ui/route/RouteFragment.kt index 8de3420c..4de88251 100644 --- a/presentation/src/main/java/com/stop/ui/route/RouteFragment.kt +++ b/presentation/src/main/java/com/stop/ui/route/RouteFragment.kt @@ -55,9 +55,7 @@ class RouteFragment : Fragment() { backPressedCallback = object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { - val navController = findNavController() - navController.setGraph(R.navigation.nav_graph) - navController.popBackStack(R.id.action_global_mapFragment, false) + findNavController().popBackStack(R.id.mapFragment, false) } } requireActivity().onBackPressedDispatcher.addCallback(this, backPressedCallback) @@ -163,7 +161,7 @@ class RouteFragment : Fragment() { requireArguments().clear() if (args?.start != null || args?.end != null) { - routeViewModel.getRoute() + routeViewModel.patchRoute() } } @@ -176,9 +174,9 @@ class RouteFragment : Fragment() { val dialogView = layoutInflater.inflate(R.layout.dialog_progress, null) alertDialog = AlertDialog.Builder(requireContext()) - .setView(dialogView) - .setCancelable(false) - .create() + .setView(dialogView) + .setCancelable(false) + .create() alertDialog.window?.setBackgroundDrawableResource(R.color.transparent) routeViewModel.alertDialog = alertDialog } diff --git a/presentation/src/main/java/com/stop/ui/route/RouteViewModel.kt b/presentation/src/main/java/com/stop/ui/route/RouteViewModel.kt index 2c81e62a..63a46eae 100644 --- a/presentation/src/main/java/com/stop/ui/route/RouteViewModel.kt +++ b/presentation/src/main/java/com/stop/ui/route/RouteViewModel.kt @@ -14,7 +14,11 @@ import com.stop.model.ErrorType import com.stop.model.Event import com.stop.model.route.Place import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import java.net.SocketTimeoutException +import java.net.UnknownHostException import javax.inject.Inject @HiltViewModel @@ -50,7 +54,17 @@ class RouteViewModel @Inject constructor( val isLoading: LiveData> get() = _isLoading - fun getRoute(isShowError: Boolean = true) { + private val coroutineExceptionHandler = CoroutineExceptionHandler { _, throwable -> + val errorMessage = when (throwable) { + is SocketTimeoutException -> Event(ErrorType.SOCKET_TIMEOUT_EXCEPTION) + is UnknownHostException -> Event(ErrorType.UNKNOWN_HOST_EXCEPTION) + else -> Event(ErrorType.UNKNOWN_EXCEPTION) + } + _errorMessage.postValue(errorMessage) + _isLoading.postValue(Event(false)) + } + + fun patchRoute(isShowError: Boolean = true) { val originValue = _origin.value ?: let { if (!isShowError) { return @@ -75,16 +89,16 @@ class RouteViewModel @Inject constructor( endY = destinationValue.coordinate.latitude, ) - viewModelScope.launch { + viewModelScope.launch(Dispatchers.Default + coroutineExceptionHandler) { val itineraries = getRouteUseCase(routeRequest) if (itineraries.isEmpty()) { - _errorMessage.value = Event(ErrorType.NO_ROUTE_RESULT) - _routeResponse.value = listOf() - _isLoading.value = Event(false) + _errorMessage.postValue(Event(ErrorType.NO_ROUTE_RESULT)) + _routeResponse.postValue(listOf()) + _isLoading.postValue(Event(false)) return@launch } - this@RouteViewModel._routeResponse.value = itineraries - _isLoading.value = Event(false) + this@RouteViewModel._routeResponse.postValue(itineraries) + _isLoading.postValue(Event(false)) } } @@ -92,13 +106,13 @@ class RouteViewModel @Inject constructor( _origin.value = _destination.value.also { _destination.value = _origin.value } - getRoute(false) + patchRoute(false) } fun calculateLastTransportTime(itinerary: Itinerary) { checkClickedItinerary(itinerary) - viewModelScope.launch { - this@RouteViewModel._lastTimeResponse.value = Event(getLastTransportTimeUseCase(itinerary) ) + viewModelScope.launch(Dispatchers.Default + coroutineExceptionHandler) { + this@RouteViewModel._lastTimeResponse.postValue(Event(getLastTransportTimeUseCase(itinerary))) } } diff --git a/presentation/src/main/java/com/stop/ui/routedetail/RouteDetailFragment.kt b/presentation/src/main/java/com/stop/ui/routedetail/RouteDetailFragment.kt index 0703b08c..89f4f185 100644 --- a/presentation/src/main/java/com/stop/ui/routedetail/RouteDetailFragment.kt +++ b/presentation/src/main/java/com/stop/ui/routedetail/RouteDetailFragment.kt @@ -6,7 +6,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.core.view.GravityCompat -import androidx.navigation.findNavController import androidx.navigation.fragment.findNavController import com.stop.R import androidx.navigation.navGraphViewModels @@ -76,8 +75,7 @@ class RouteDetailFragment : Fragment(), RouteDetailHandler { binding.imageViewClose.setOnClickListener { findNavController().apply { - setGraph(R.navigation.nav_graph) - popBackStack(R.id.action_global_mapFragment, false) + popBackStack(R.id.mapFragment, false) requireActivity().viewModelStore.clear() } } diff --git a/presentation/src/main/res/navigation/nav_graph.xml b/presentation/src/main/res/navigation/nav_graph.xml index b416bc52..6d681114 100644 --- a/presentation/src/main/res/navigation/nav_graph.xml +++ b/presentation/src/main/res/navigation/nav_graph.xml @@ -5,14 +5,26 @@ android:id="@+id/nav_graph" app:startDestination="@id/mapFragment"> - - + + + + @@ -35,9 +47,49 @@ app:destination="@id/mapFragment" /> - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml index dc747109..cd04a2a7 100644 --- a/presentation/src/main/res/values/strings.xml +++ b/presentation/src/main/res/values/strings.xml @@ -80,6 +80,9 @@ 도착지 : %1$s 막차시간 : %1$s %1$d분 + API 서버가 응답하지 않습니다. 다시 시도해주세요. + 알 수 없는 에러가 발생했습니다. + 인터넷이 연결되어 있지 않거나, 페쇄망 호스트에 연결을 시도했습니다. 알람이 %1$s의 %2$s분 전에 울릴 예정입니다. 알람을 설정할 수 없습니다 분 전