Skip to content

Instantly share code, notes, and snippets.

@ankitchauhan20
Created July 26, 2022 12:32
Show Gist options
  • Save ankitchauhan20/35976b3a3805d30eb6cc444d166dd2c2 to your computer and use it in GitHub Desktop.
Save ankitchauhan20/35976b3a3805d30eb6cc444d166dd2c2 to your computer and use it in GitHub Desktop.
Dagger with Retrofit MVVM
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.activity.MainActivity"
>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.example.dagger2.view.fragment.PostFragment"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
package com.example.di
import com.example.dagger2.model.dataModel.PostItem
import retrofit2.Call
import retrofit2.http.GET
interface ApiService {
@GET("/posts")
fun getPost(): Call<List<PostItem>>
}
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
id 'kotlin-android-extensions'
}
android {
compileSdk 32
defaultConfig {
applicationId "com.example.dagger2"
minSdk 23
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
android {
viewBinding {
enabled = true
}
dataBinding{
enabled = true
}
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation("androidx.recyclerview:recyclerview:1.2.1")
implementation("androidx.cardview:cardview:1.0.0")
implementation 'com.google.code.gson:gson:2.8.7'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation("com.squareup.okhttp3:logging-interceptor:4.10.0")
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
implementation "android.arch.lifecycle:viewmodel:1.1.0"
implementation 'com.google.dagger:dagger:2.43'
kapt 'com.google.dagger:dagger-compiler:2.43'
}
package com.example.dagger2.utils
object Constants {
val baseURL = "https://jsonplaceholder.typicode.com/"
}
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.fragment.PostFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/postRecycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
</layout>
package com.example.dagger2.view.activity
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.example.dagger2.application.MyApplication
import com.example.dagger2.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
lateinit var binding : ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, com.example.dagger2.R.layout.activity_main)
(application as MyApplication).retroComponent.inject(this)
}
}
package com.example.dagger2.application
import android.app.Application
import com.example.di.DaggerRetroComponent
import com.example.di.RetroComponent
import com.example.di.RetroModule
class MyApplication: Application() {
lateinit var retroComponent: RetroComponent
override fun onCreate() {
super.onCreate()
retroComponent = DaggerRetroComponent.builder()
.retroModule(RetroModule())
.build()
}
}
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="170dp"
android:layout_margin="10dp"
app:cardElevation="5dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/post_Id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="5dp"
android:text="Id"
android:textSize="18dp"
android:textStyle="bold"
android:textColor="#6C0808"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/post_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="Title"
android:textSize="16dp"
android:textStyle="bold"
android:textColor="#051C6E"
app:layout_constraintTop_toBottomOf="@id/post_Id"
app:layout_constraintStart_toStartOf="@id/post_Id"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/post"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="Post"
android:textSize="15dp"
android:textColor="#000"
app:layout_constraintTop_toBottomOf="@id/post_title"
app:layout_constraintStart_toStartOf="@id/post_title"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
package com.example.dagger2.view.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.RecyclerView
import com.example.dagger2.R
import com.example.dagger2.databinding.PostItemBinding
import com.example.dagger2.model.dataModel.PostItem
class PostAdapter() : RecyclerView.Adapter<PostAdapter.ViewHolder>() {
var binding : PostItemBinding? = null
private lateinit var list: List<PostItem>
constructor(data: List<PostItem>) : this() {
this.list = data
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
binding = DataBindingUtil.inflate(LayoutInflater.from(parent.context), R.layout.post_item, parent, false)
return ViewHolder(binding!!)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val postItem: PostItem = list.get(position)
holder.bindData(postItem)
}
override fun getItemCount(): Int {
return list.size
}
class ViewHolder(private val viewBinding: PostItemBinding): RecyclerView.ViewHolder(viewBinding.root) {
fun bindData(postItem: PostItem){
viewBinding.postId.text = postItem.id
viewBinding.postTitle.text = postItem.title
viewBinding.post.text = postItem.body
}
}
}
package com.example.dagger2.view.fragment
import android.app.Activity
import android.content.Context
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.dagger2.application.MyApplication
import com.example.dagger2.databinding.FragmentPostBinding
import com.example.dagger2.view.adapter.PostAdapter
import com.example.dagger2.viewModel.PostViewModel
import com.example.dagger2.viewModel.PostViewModelFactory
import javax.inject.Inject
class PostFragment : Fragment() {
lateinit var binding: FragmentPostBinding
lateinit var postViewModel: PostViewModel
private var mActivity: Context? = null
@Inject
lateinit var postViewModelFactory: PostViewModelFactory
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.postRecycler.layoutManager = LinearLayoutManager(context)
binding.postRecycler.setHasFixedSize(true)
postViewModel.makeApiCall()
}
override fun onAttach(context: Context) {
super.onAttach(context)
mActivity = context as Activity
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?,
): View? {
binding = FragmentPostBinding.inflate(inflater, container, false )
((mActivity as Activity).application as MyApplication).retroComponent.inject(this)
initViewModel()
return binding.root
}
private fun initViewModel() {
postViewModel = ViewModelProvider(this, postViewModelFactory).get(PostViewModel::class.java)
postViewModel.liveDataList.observe(viewLifecycleOwner, Observer{
binding!!.postRecycler.adapter = PostAdapter(it)
})
}
}
package com.example.dagger2.model.dataModel
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
import kotlinx.android.parcel.Parcelize
@Parcelize
data class PostItem(
@SerializedName("id")
var id: String,
@SerializedName("body")
var body: String,
@SerializedName("title")
var title: String
): Parcelable
package com.example.dagger2.model.repository
import com.example.di.ApiService
import javax.inject.Inject
class PostRepository @Inject constructor( private val apiService: ApiService) {
fun getAllPost() = apiService.getPost()
}
package com.example.dagger2.viewModel
import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.example.dagger2.model.dataModel.PostItem
import com.example.dagger2.model.repository.PostRepository
import com.example.di.ApiService
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import javax.inject.Inject
class PostViewModel(val repository: PostRepository): ViewModel() {
@Inject
lateinit var mService : ApiService
var liveDataList : MutableLiveData<List<PostItem>> = MutableLiveData()
fun makeApiCall(){
val response = repository.getAllPost()
response.enqueue(object : Callback<List<PostItem>> {
override fun onResponse(
call: Call<List<PostItem>>,
response: Response<List<PostItem>>,
) {
val data = response.body() as List<PostItem>
liveDataList.value = data
Log.e("Tag", ""+response.body())
}
override fun onFailure(call: Call<List<PostItem>>, t: Throwable) {
Log.e("Fail", "${t.message}")
}
})
}
}
package com.example.dagger2.viewModel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.example.dagger2.model.repository.PostRepository
import javax.inject.Inject
class PostViewModelFactory @Inject constructor(private val repository: PostRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return PostViewModel(repository) as T
}
}
package com.example.di
import com.example.dagger2.view.activity.MainActivity
import com.example.dagger2.view.fragment.PostFragment
import dagger.Component
import javax.inject.Singleton
@Singleton
@Component(modules = [RetroModule::class])
interface RetroComponent {
fun inject(activity:MainActivity)
fun inject(fragment: PostFragment)
}
package com.example.di
import com.example.dagger2.utils.Constants
import dagger.Module
import dagger.Provides
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import javax.inject.Singleton
@Module
class RetroModule {
@Singleton
@Provides
fun getRetrofitInstance() : Retrofit{
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val builder = OkHttpClient.Builder()
.addInterceptor(interceptor)
return Retrofit.Builder()
.baseUrl(Constants.baseURL)
.client(builder.build())
.addConverterFactory(GsonConverterFactory.create())
.build()
}
@Singleton
@Provides
fun getApiService(retrofit: Retrofit): ApiService{
return retrofit.create(ApiService::class.java)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment