Skip to content

Commit f95d356

Browse files
author
Vimalraj Vijay
committed
NetWork Call Using Coroutines
1 parent 5ea2df1 commit f95d356

File tree

12 files changed

+122
-72
lines changed

12 files changed

+122
-72
lines changed

app/build.gradle

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,23 +48,14 @@ dependencies {
4848
//Android Activity ViewModel -- Generates ViewModels()
4949
implementation "androidx.activity:activity-ktx:1.1.0"
5050

51-
//Recycler View
52-
implementation "androidx.recyclerview:recyclerview:1.1.0"
53-
//Glide - Load Images
54-
implementation 'com.github.bumptech.glide:glide:4.9.0'
55-
5651
//Android LifeCycle
5752
implementation 'android.arch.lifecycle:extensions:1.1.1'
5853
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
5954
implementation "androidx.lifecycle:lifecycle-common-java8:2.2.0"
6055

6156
//Retrofit
6257
implementation 'com.squareup.retrofit2:retrofit:2.7.2'
63-
implementation "com.squareup.retrofit2:adapter-rxjava2:2.7.2"
64-
65-
//Rx Java
66-
implementation 'io.reactivex.rxjava2:rxjava:2.2.18'
67-
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
58+
implementation "com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2"
6859

6960
//OkHttp Client and Logger
7061
implementation "com.squareup.okhttp3:okhttp:3.14.7"
@@ -74,6 +65,11 @@ dependencies {
7465
implementation 'com.google.code.gson:gson:2.8.5'
7566
implementation 'com.squareup.retrofit2:converter-gson:2.7.2'
7667

68+
// Coroutines
69+
def kotlinCoroutineVersion = "1.3.0"
70+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutineVersion"
71+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutineVersion"
72+
7773
//Dagger Hilt
7874
implementation "com.google.dagger:hilt-android:$hilt_version"
7975
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
android:roundIcon="@mipmap/ic_launcher_round"
1212
android:supportsRtl="true"
1313
android:theme="@style/Theme.Dagger2">
14-
<activity android:name=".MainActivity">
14+
<activity android:name=".main.ui.MainActivity">
1515
<intent-filter>
1616
<action android:name="android.intent.action.MAIN" />
1717

app/src/main/java/com/vimalvijay/dagger2/di/ApplicationController.kt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@ import android.app.Application
44
import dagger.hilt.android.HiltAndroidApp
55

66
@HiltAndroidApp
7-
class ApplicationController :Application(){
8-
9-
override fun onCreate() {
10-
super.onCreate()
11-
}
7+
class ApplicationController : Application() {
128

139
}
Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.vimalvijay.dagger2.di.modules
22

3+
import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory
34
import com.vimalvijay.dagger2.BuildConfig
45
import com.vimalvijay.dagger2.network.ApiConstants
56
import com.vimalvijay.dagger2.network.ApiService
@@ -10,21 +11,25 @@ import dagger.hilt.android.components.ApplicationComponent
1011
import okhttp3.OkHttpClient
1112
import okhttp3.logging.HttpLoggingInterceptor
1213
import retrofit2.Retrofit
13-
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
1414
import retrofit2.converter.gson.GsonConverterFactory
1515
import javax.inject.Singleton
1616

1717

1818
@Module
1919
@InstallIn(ApplicationComponent::class)
2020
class AppModule {
21-
21+
/**
22+
* Application's Base URL
23+
*/
2224
@Provides
2325
fun providesAppBaseURL() = ApiConstants.BASE_URL
2426

27+
/**
28+
* Logger For API
29+
*/
2530
@Provides
2631
@Singleton
27-
fun provideOkHttpClient() = if (BuildConfig.DEBUG) {
32+
fun provideOkHttpClient(): OkHttpClient = if (BuildConfig.DEBUG) {
2833
val loggingInterceptor = HttpLoggingInterceptor()
2934
loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
3035
OkHttpClient.Builder()
@@ -34,17 +39,23 @@ class AppModule {
3439
.Builder()
3540
.build()
3641

42+
/**
43+
* Init Retrofit Client for Network
44+
*/
3745
@Provides
3846
@Singleton
3947
fun provideRetrofit(okHttpClient: OkHttpClient, BASE_URL: String): Retrofit =
4048
Retrofit.Builder()
4149
.addConverterFactory(GsonConverterFactory.create())
42-
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
50+
.addCallAdapterFactory(CoroutineCallAdapterFactory())
4351
.baseUrl(BASE_URL)
4452
.client(okHttpClient)
4553
.build()
4654

55+
/**
56+
* Api Provider
57+
*/
4758
@Provides
4859
@Singleton
49-
fun provideApiService(retrofit: Retrofit) = retrofit.create(ApiService::class.java)
60+
fun provideApiService(retrofit: Retrofit): ApiService = retrofit.create(ApiService::class.java)
5061
}
Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,22 @@
11
package com.vimalvijay.dagger2.main.repository
22

3-
import androidx.lifecycle.MutableLiveData
43
import com.vimalvijay.dagger2.main.model.Hero
54
import com.vimalvijay.dagger2.network.ApiService
6-
import retrofit2.Call
7-
import retrofit2.Callback
8-
import retrofit2.Response
5+
import com.vimalvijay.dagger2.network.BaseRepository
96
import javax.inject.Inject
107

118

12-
class MainRepository @Inject constructor(var apiService: ApiService) {
9+
class MainRepository @Inject constructor(var apiService: ApiService) : BaseRepository() {
1310

14-
val heroList: MutableLiveData<Hero> = MutableLiveData()
11+
/**
12+
* Get Hero List from Api
13+
*/
14+
suspend fun getHerosList(): MutableList<Hero.HeroItem>? {
1515

16-
17-
fun getHeroListCall(): MutableLiveData<Hero> {
18-
apiService.getHeroes().enqueue(object : Callback<Hero?> {
19-
override fun onFailure(call: Call<Hero?>, t: Throwable) {
20-
println("Error throw ${t.localizedMessage}")
21-
heroList.postValue(null)
22-
}
23-
24-
override fun onResponse(call: Call<Hero?>, response: Response<Hero?>) {
25-
val callheroList: Hero = response.body() as Hero
26-
heroList.value = response.body()
27-
}
28-
29-
})
30-
31-
return heroList
16+
val heroResponse = safeApiRequest(
17+
call = { apiService.getHeroes().await() },
18+
errorMessage = "Error On" + Thread.currentThread().stackTrace[1].methodName
19+
)
20+
return heroResponse?.toMutableList()
3221
}
3322
}

app/src/main/java/com/vimalvijay/dagger2/MainActivity.kt renamed to app/src/main/java/com/vimalvijay/dagger2/main/ui/MainActivity.kt

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.vimalvijay.dagger2
1+
package com.vimalvijay.dagger2.main.ui
22

33
import android.os.Bundle
44
import android.view.LayoutInflater
@@ -8,6 +8,7 @@ import android.widget.TextView
88
import androidx.activity.viewModels
99
import androidx.appcompat.app.AppCompatActivity
1010
import androidx.lifecycle.Observer
11+
import com.vimalvijay.dagger2.R
1112
import com.vimalvijay.dagger2.main.model.Hero
1213
import com.vimalvijay.dagger2.main.viewmodel.MainViewModel
1314
import dagger.hilt.android.AndroidEntryPoint
@@ -23,19 +24,26 @@ class MainActivity : AppCompatActivity() {
2324
override fun onCreate(savedInstanceState: Bundle?) {
2425
super.onCreate(savedInstanceState)
2526
setContentView(R.layout.activity_main)
26-
mainViewModel.getHerosRepository().observe(this, object : Observer<Hero> {
27-
override fun onChanged(t: Hero?) {
28-
t?.let { generateView(it) }
29-
}
30-
})
27+
28+
/**
29+
* Fetch
30+
*/
31+
mainViewModel.fetchHerosList()
32+
/**
33+
* Observe Using Live data
34+
*/
35+
mainViewModel.heroListLiveData.observe(this, Observer<MutableList<Hero.HeroItem>> { t -> generateView(t) })
3136
}
3237

33-
private fun generateView(hero: Hero) {
38+
/**
39+
* Set Views
40+
*/
41+
private fun generateView(hero: MutableList<Hero.HeroItem>?) {
3442
val parentLayout = findViewById<LinearLayout>(R.id.llt_heros_list)
3543
val layoutInflater: LayoutInflater = layoutInflater
3644

3745
parentLayout.removeAllViews()
38-
for (i in hero.indices) {
46+
for (i in hero?.indices!!) {
3947
view = layoutInflater.inflate(R.layout.heros_name_list, parentLayout, false)
4048
val tvHeroNames = view.findViewById<TextView>(R.id.tv_hero_names)
4149
tvHeroNames.text = hero[i].name

app/src/main/java/com/vimalvijay/dagger2/main/viewmodel/MainViewModel.kt

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,31 @@ import androidx.lifecycle.MutableLiveData
55
import androidx.lifecycle.ViewModel
66
import com.vimalvijay.dagger2.main.model.Hero
77
import com.vimalvijay.dagger2.main.repository.MainRepository
8+
import kotlinx.coroutines.*
9+
import kotlin.coroutines.CoroutineContext
810

911
class MainViewModel @ViewModelInject constructor(private var mainRepository: MainRepository) :
1012
ViewModel() {
1113

12-
var heroList: MutableLiveData<Hero> = MutableLiveData()
14+
private val parentJob = Job()
1315

14-
fun getHerosRepository(): MutableLiveData<Hero> {
15-
heroList = loadHerosList()
16-
return heroList
16+
private val coroutineContext: CoroutineContext
17+
get() = parentJob + Dispatchers.Default
18+
19+
private val scope = CoroutineScope(coroutineContext)
20+
21+
val heroListLiveData = MutableLiveData<MutableList<Hero.HeroItem>>()
22+
23+
/**
24+
* Launch API using Coroutines
25+
*/
26+
fun fetchHerosList() {
27+
scope.launch {
28+
heroListLiveData.postValue(mainRepository.getHerosList())
29+
}
1730
}
1831

19-
private fun loadHerosList(): MutableLiveData<Hero> {
20-
return mainRepository.getHeroListCall()
32+
fun cancelAllRequest() {
33+
coroutineContext.cancel()
2134
}
22-
}
35+
}

app/src/main/java/com/vimalvijay/dagger2/network/ApiConstants.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,4 @@ package com.vimalvijay.dagger2.network
22

33
object ApiConstants {
44
const val BASE_URL = "https://simplifiedcoding.net/demos/"
5-
6-
const val RESPONSE_SUCCESS = "Success"
7-
const val RESPONSE_FAILURE = "Failure"
8-
const val RESPONSE_LOADING = "Loading"
95
}
Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
11
package com.vimalvijay.dagger2.network
22

33
import com.vimalvijay.dagger2.main.model.Hero
4-
import io.reactivex.Single
5-
import retrofit2.Call
4+
import kotlinx.coroutines.Deferred
5+
import retrofit2.Response
66
import retrofit2.http.GET
77

88
interface ApiService {
99

1010
@GET("marvel")
11-
fun getHeroes(): Call<Hero>
12-
13-
/*@GET("repos/{owner}/{name}")
14-
fun getRepo(
15-
@Path("owner") owner: String?,
16-
@Path("name") name: String?
17-
): Single<Repo?>?*/
11+
fun getHeroes(): Deferred<Response<Hero>>
1812

1913
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.vimalvijay.dagger2.network
2+
3+
import android.util.Log
4+
import retrofit2.Response
5+
import java.io.IOException
6+
7+
open class BaseRepository {
8+
9+
/**
10+
* Api Calling
11+
*/
12+
suspend fun <T : Any> safeApiRequest(
13+
call: suspend () -> Response<T>,
14+
errorMessage: String
15+
): T? {
16+
val result: NetworkResultHandler<T> = safeApiResult(call, errorMessage)
17+
var data: T? = null
18+
19+
when (result) {
20+
is NetworkResultHandler.OnSuccessResponse ->
21+
data = result.response
22+
is NetworkResultHandler.OnFailureResponse ->
23+
Log.d("1.DataRepository", "$errorMessage & Exception - ${result.exception}")
24+
}
25+
26+
return data
27+
}
28+
29+
/**
30+
* NetWork Result Handler
31+
*/
32+
private suspend fun <T : Any> safeApiResult(
33+
call: suspend () -> Response<T>,
34+
errorMessage: String
35+
): NetworkResultHandler<T> {
36+
val response = call.invoke()
37+
if (response.isSuccessful) return NetworkResultHandler.OnSuccessResponse(response.body()!!)
38+
39+
return NetworkResultHandler.OnFailureResponse(IOException("Error Occurred during getting safe Api result, Custom ERROR - $errorMessage"))
40+
}
41+
}

0 commit comments

Comments
 (0)