11package com.sijanneupane.mvvmnews.ui
22
3+ import android.app.Application
4+ import android.content.Context
5+ import android.net.ConnectivityManager
6+ import android.net.NetworkCapabilities.*
7+ import androidx.lifecycle.AndroidViewModel
38import androidx.lifecycle.MutableLiveData
49import androidx.lifecycle.ViewModel
510import androidx.lifecycle.viewModelScope
11+ import com.sijanneupane.mvvmnews.NewsApplication
612import com.sijanneupane.mvvmnews.models.Article
713import com.sijanneupane.mvvmnews.models.NewsResponse
814import com.sijanneupane.mvvmnews.repository.NewsRepository
915import com.sijanneupane.mvvmnews.utils.Resource
1016import kotlinx.coroutines.launch
1117import retrofit2.Response
18+ import java.io.IOException
1219
1320class NewsViewModel (
21+ app : Application ,
1422 val newsRepository : NewsRepository // parameter
15- ) : ViewModel(){
23+ ) : AndroidViewModel(app){ // inheriting from android view model to use application context
24+ // here we use application context to get the context throughout the app running,
25+ // so it will work even if the activity changes or destroys, the app context will still work until the app's running
1626
1727 // LIVEDATA OBJECT
1828 val breakingNews: MutableLiveData <Resource <NewsResponse >> = MutableLiveData ()
@@ -34,24 +44,25 @@ class NewsViewModel(
3444 viewModelScope makes the function alive only as long as the ViewModel is alive
3545 */
3646 fun getBreakingNews (countryCode : String )= viewModelScope.launch {
37- breakingNews.postValue(Resource .Loading ()) // init loading state before the network call
38-
47+ // breakingNews.postValue(Resource.Loading()) //init loading state before the network call
48+ safeBreakingNewsCall(countryCode)
3949 // actual response
40- val response= newsRepository.getBreakingNews(countryCode, breakingNewsPage)
50+ // val response= newsRepository.getBreakingNews(countryCode, breakingNewsPage)
4151
4252 // handling response
43- breakingNews.postValue(handleBreakingNewsResponse(response))
53+ // breakingNews.postValue(handleBreakingNewsResponse(response))
4454 }
4555
4656
4757 fun searchNews (searchQuery : String )= viewModelScope.launch {
48- searchNews.postValue(Resource .Loading ()) // init loading state before the network call
58+ safeSearchNewsCall(searchQuery)
59+ // searchNews.postValue(Resource.Loading()) //init loading state before the network call
4960
5061 // actual response
51- val response= newsRepository.searchNews(searchQuery, searchNewsPage)
62+ // val response= newsRepository.searchNews(searchQuery, searchNewsPage)
5263
5364 // handling response
54- searchNews.postValue(handleSearchNewsResponse(response))
65+ // searchNews.postValue(handleSearchNewsResponse(response))
5566 }
5667
5768
@@ -108,4 +119,58 @@ class NewsViewModel(
108119 newsRepository.deleteArticle(article)
109120 }
110121
122+ private suspend fun safeBreakingNewsCall (countryCode : String ){
123+ breakingNews.postValue(Resource .Loading ())
124+ try {
125+ if (hasInternetConnection()){
126+ val response= newsRepository.getBreakingNews(countryCode, breakingNewsPage)
127+ // handling response
128+ breakingNews.postValue(handleBreakingNewsResponse(response))
129+ }else {
130+ breakingNews.postValue(Resource .Error (" No Internet Connection" ))
131+ }
132+
133+ } catch (t: Throwable ){
134+ when (t){
135+ is IOException -> breakingNews.postValue(Resource .Error (" Network Failure" ))
136+ else -> breakingNews.postValue(Resource .Error (" Conversion Error" ))
137+ }
138+ }
139+ }
140+
141+ private suspend fun safeSearchNewsCall (searchQuery : String ){
142+ searchNews.postValue(Resource .Loading ())
143+ try {
144+ if (hasInternetConnection()){
145+ val response= newsRepository.searchNews(searchQuery, searchNewsPage)
146+ // handling response
147+ searchNews.postValue(handleSearchNewsResponse(response))
148+ }else {
149+ searchNews.postValue(Resource .Error (" No Internet Connection" ))
150+ }
151+
152+ } catch (t: Throwable ){
153+ when (t){
154+ is IOException -> searchNews.postValue(Resource .Error (" Network Failure" ))
155+ else -> searchNews.postValue(Resource .Error (" Conversion Error" ))
156+ }
157+ }
158+ }
159+
160+
161+ private fun hasInternetConnection (): Boolean {
162+ val connectivityManager= getApplication<NewsApplication >().getSystemService(
163+ Context .CONNECTIVITY_SERVICE
164+ ) as ConnectivityManager
165+
166+ val activeNetwork= connectivityManager.activeNetwork? : return false
167+ val capabilities= connectivityManager.getNetworkCapabilities(activeNetwork)? : return false
168+
169+ return when {
170+ capabilities.hasTransport(TRANSPORT_WIFI )-> true
171+ capabilities.hasTransport(TRANSPORT_CELLULAR )-> true
172+ capabilities.hasTransport(TRANSPORT_ETHERNET )-> true
173+ else -> false
174+ }
175+ }
111176}
0 commit comments