My RecyclerView in ViewModel crashing app - kotlin android studio - kotlin

I have problem with RecyclerView into ViewModel.
RecyclerView without viewmodel working perfect.
My MainFragment:
private lateinit var shoppingListViewModel: ShoppingListViewModel
private lateinit var categoryAdapter: CategoryAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
shoppingListViewModel = ViewModelProvider(requireActivity())[ShoppingListViewModel::class.java]
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.categoryRV.layoutManager = LinearLayoutManager(requireContext())
shoppingListViewModel.allCategories.observe(viewLifecycleOwner, { <-- when I add this line,
updateCategories(it) crashing my app
})
}
private fun updateCategories(list: List<Category>) {
categoryAdapter = CategoryAdapter(list)
binding.categoryRV.adapter = categoryAdapter
}
My ViewModel:
class ShoppingListViewModel(application: Application) : AndroidViewModel(application) {
private val repository = Repository(application)
val allCategories = repository.showAllCategories()
}
My Repo:
class Repository(app: Application) {
private val shoppingListsDao = ShoppingListDatabaseBuilder.getInstance(app.applicationContext).shoppingListDao()
fun showAllCategories(): LiveData<List<Category>> {
return shoppingListsDao.showAllCategories()
}
}
My Interface Dao:
#Dao
interface ShoppingListDao {
#Query("SELECT * FROM category")
fun showAllCategories(): LiveData<List<Category>>
}
Everything looks good, no errors. I don't know what going on :(

I find my problem.
I need to update of version DB :)

Related

MVVM Navigation fragments switch, but change is not visible

I am trying to build a simple app in Kotlin using MVVM architecture, and I'm struggling with switching fragments. I get it to "change" - on a button press it does nothing, and on a second press it crashes saying "Navigation action/destination MAIN_to_RESULT cannot be found from the current destination RESULT" - so it clearly changed the fragments from MAIN to RESULT, but I still see the MAIN fragment)
Here is my MAIN fragment:
class MainFragment : Fragment() {
private lateinit var viewModel: MainViewModel
lateinit var binding: FragmentMainBinding
companion object {
fun newInstance() = MainFragment()
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = (activity as MainActivity).viewModel
binding.setVariable(myViewModel, viewModel)
viewModel.bnd = binding
binding.button2.setOnClickListener { viewModel.chng() }
binding.submitButton.setOnClickListener {
val controller = NavHostFragment.findNavController(this)
controller.navigate(R.id.action_mainFragment_to_resultFragment)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_main, container, false)
binding.setLifecycleOwner(this)
return binding.root
}
}
OTHER fragment:
class ResultFragment : Fragment() {
private lateinit var viewModel: MainViewModel
lateinit var binding: FragmentMainBinding
companion object {
fun newInstance() = ResultFragment()
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_main, container, false)
binding.setLifecycleOwner(this)
return binding.root
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = (activity as MainActivity).viewModel
binding.setVariable(BR.myViewModel, viewModel)
binding.button2.setOnClickListener { viewModel.chng() }
viewModel.bnd = binding
}
}
MainViewModel:
class MainViewModel(application: Application) : AndroidViewModel(application) {
val rps = Repository()
lateinit var bnd : FragmentMainBinding
var changing = false
var SPEED_OF_CHANGING = 100L
var actualCountedCards = 0
var numberOfCardsToRotate = 0
var numberOfRotatedCards = 0
lateinit var actualCard : Card
var mainHandler: Handler = Handler(Looper.getMainLooper())
private val changeCard = object : Runnable {
override fun run() {
if (changing) {
actualCard = rps.Cards.random()
bnd.cardView.setImageResource(actualCard.image)
actualCountedCards += actualCard.power
numberOfRotatedCards += 1
Log.d("tagicek", "${numberOfRotatedCards}/${numberOfCardsToRotate}, ${actualCountedCards}")
if (numberOfRotatedCards >= numberOfCardsToRotate) {
chng()
bnd.editTextTextPersonName.visibility = View.VISIBLE
bnd.submitButton.visibility = View.VISIBLE
bnd.button2.visibility = View.INVISIBLE
}
mainHandler.postDelayed(this, SPEED_OF_CHANGING)
}
}
}
fun chng() {
if (changing == true) {
mainHandler.removeCallbacks(changeCard)
actualCountedCards = 0
numberOfRotatedCards = 0
bnd.cardView.setImageResource(R.drawable.bg)
changing = false
} else {
numberOfCardsToRotate = (1..51).random()
mainHandler.post(changeCard)
changing = true
}
}
}
MainActivity:
class MainActivity : AppCompatActivity() {
lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this)[MainViewModel::class.java]
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, MainFragment.newInstance())
.commitNow()
}
}
}
I am pretty sure the problem is with my bindings and views, but I can't wrap my head around it. I have tried probably every positioning of defining the NavController and the different views passed into it, but it still doesn't work.

RecyclerView with coroutines, using Fragment doesn't populate data Kotlin

I am trying to work wih courutines and recycler view. I've done everything necessary to send requests to the API, but I still can't get the list that should be inside the recycler view. I am using fragment to create list and bottom nav. When I go to the fragment where my list should be, then I get the error: RecyclerView: No layout manager attached; skipping layoutand nothing more. I googled about this error and it says I should define the layout manager in xml, but it alreadt has layuout manager in my fragment
<androidx.recyclerview.widget.RecyclerView 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"
android:id="#+id/list_item"
app:layoutManager="LinearLayoutManager"
Also my adapter and fragment for recycler view look like this:
class MyItemRecyclerViewAdapter(
) : RecyclerView.Adapter<MyItemRecyclerViewAdapter.ViewHolder>() {
var userNameResponse = mutableListOf<UsersNameItem>()
fun setNamesList(names: List<UsersNameItem>) {
this.userNameResponse = userNameResponse.toMutableList()
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
FragmentItemBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = userNameResponse[position]
holder.idView.text = item.id
holder.contentView.text = item.name
}
override fun getItemCount(): Int = userNameResponse.size
class ViewHolder(binding: FragmentItemBinding) : RecyclerView.ViewHolder(binding.root) {
val idView: TextView = binding.itemNumber
val contentView: TextView = binding.content
}
}
Fragment:
class ItemFragment : Fragment() {
private var layoutManager: RecyclerView.LayoutManager? = null
private var adapter: RecyclerView.Adapter<MyItemRecyclerViewAdapter.ViewHolder>? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_item_list, container, false)
}
override fun onViewCreated(itemView: View, savedInstanceState: Bundle?) {
super.onViewCreated(itemView, savedInstanceState)
layoutInflater.apply {
layoutManager = LinearLayoutManager(activity)
adapter = MyItemRecyclerViewAdapter()
}
}
companion object {
fun newInstance() = ItemFragment()
}
}
And MainActivity where I set up courutines and trying to make a request:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
lateinit var nameviewModel: ListNamesViewModel
val adapter = MyItemRecyclerViewAdapter()
///trying to create http-request for lists
val retrofitService = BasicApiService.getInstance()
val mainRepository = MainRepository(retrofitService)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
nameviewModel = ViewModelProvider(
this,
MyViewModelFactory(mainRepository)
)[ListNamesViewModel::class.java]
nameviewModel.userName.observe(
this, Observer {
adapter.setNamesList(it)
})
nameviewModel.message.observe(this) {
Toast.makeText(this, it, Toast.LENGTH_SHORT).show()
}
nameviewModel.loadUsers()
val navView: BottomNavigationView = binding.navView
val navController = findNavController(R.id.nav_host_fragment_activity_main)
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_home,
R.id.navigation_dashboard,
R.id.navigation_notifications,
R.id.list_name_navig
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
}
Also I wanted to ask (I am very new to Kotlin nad just trying to make things work) if it is a good practice to leave request to API in the MainActivity ot I should do it in another way?
I see some confusion in your code, try to apply the next:
Why are you creating the layoutManager and adapter in the ItemFragment?
override fun onViewCreated(itemView: View, savedInstanceState: Bundle?) {
super.onViewCreated(itemView, savedInstanceState)
layoutInflater.apply {
layoutManager = LinearLayoutManager(activity)
adapter = MyItemRecyclerViewAdapter()
}
}
You need to move it and RecyclerView to your activity.
The using layoutInflater.apply {} doesn't make sense, it's doing nothing in your case. You need to set layoutManager and adapter to recyclerView then in the activity it should look like that (and rename list_item to recyclerView)
binding.recyclerView.apply {
layoutManager = LinearLayoutManager(this)
adapter = MyItemRecyclerViewAdapter()
}
Remove app:layoutManager="LinearLayoutManager" from XML.
It looks like you don't need to use ItemFragment for your purpose because you use it just like a view and binding in the ViewHolder
class ViewHolder(binding: FragmentItemBinding) : RecyclerView.ViewHolder(binding.root) {
val idView: TextView = binding.itemNumber
val contentView: TextView = binding.content
}
try changing in xml
app:layoutManager="LinearLayoutManager"
to
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"

Can't log any data from API call

I'm pretty new to kotlin, and I feel pretty much overwhelmed by it. I'd like to ask - how I can display any data from MutableLiveData? I've tried to Log it, but it doesn't seem to work. I've already added the internet permission to the manifest. Here's the code:
ApiServices
interface ApiServices {
#GET("/fixer/latest/")
fun getRatesData(
#Query("base") base: String,
#Query("apikey") apikey: String
): Call<CurrencyModel>
companion object {
private const val url = "https://api.apilayer.com/"
var apiServices: ApiServices? = null
fun getInstance(): ApiServices {
if (apiServices == null) {
val retrofit = Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build()
apiServices = retrofit.create(ApiServices::class.java)
}
return apiServices!!
}
}
}
Repository
class CurrencyRepository constructor(private val apiServices: ApiServices) {
fun getLatestRates() = apiServices.getRatesData("EUR", "API_KEY");
}
ViewModel
class CurrencyViewModel constructor(private val currencyRepository: CurrencyRepository) :
ViewModel() {
val currencyRatesList = MutableLiveData<CurrencyModel>()
val errorMessage = MutableLiveData<String>()
fun getLatestRates() {
val response = currencyRepository.getLatestRates();
response.enqueue(object : retrofit2.Callback<CurrencyModel> {
override fun onResponse(
call: retrofit2.Call<CurrencyModel>,
response: Response<CurrencyModel>
) {
currencyRatesList.postValue(response.body())
}
override fun onFailure(call: retrofit2.Call<CurrencyModel>, t: Throwable) {
errorMessage.postValue(t.message)
}
})
}
}
FactoryViewModel
class CurrencyViewModelFactory constructor(private val repository: CurrencyRepository) :
ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return if (modelClass.isAssignableFrom(CurrencyViewModel::class.java)) {
CurrencyViewModel(this.repository) as T
}else{
throw IllegalArgumentException("Couldn't found ViewModel")
}
}
}
MainActivity
class MainActivity : AppCompatActivity() {
private val retrofitService = ApiServices.getInstance()
lateinit var viewModel: CurrencyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this, CurrencyViewModelFactory(CurrencyRepository(retrofitService)))
.get(CurrencyViewModel::class.java)
viewModel.currencyRatesList.observe(this, Observer {
Log.d(TAG, "onCreate: $it")
})
viewModel.errorMessage.observe(this, Observer {
viewModel.getLatestRates()
})
}
}
You never call viewModel.getLatestRates() in your onCreate() to fetch an initial value for your LiveData, so it never emits anything to observe. The only place you have called it is inside your error listener, which won't be called until a fetch returns an error.
Side note, I recommend naming the function "fetchLatestRates()". By convention, "get" implies that the function returns what it's getting immediately rather than passing it to a LiveData later when its ready.
And a tip. Instead of this:
class MainActivity : AppCompatActivity() {
lateinit var viewModel: CurrencyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ...
viewModel = ViewModelProvider(this, CurrencyViewModelFactory(CurrencyRepository(retrofitService)))
.get(CurrencyViewModel::class.java)
//...
}
}
You can do this for the same result:
class MainActivity : AppCompatActivity() {
val viewModel: CurrencyViewModel by viewModels(CurrencyViewModelFactory(CurrencyRepository(retrofitService)))
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ...
}
}

RecyclerView in Fragment not populating

So I've been wrestling with this for days and I need some help. I've made this code work in an activity, but then I move it to a fragment it doesn't work. Everything else is the same between the two.
Using the debugger with the working Activity, the line
apiService = retrofit.create<HomeJsonApiService>(HomeJsonApiService::class.java)
goes to getItemCount(). However in the fragment it goes directly to onCreateView in the Fragment. I've attached my code below. Thanks in advance for the help! And be gentle. I'm still new to this :)
First is my fragment:
class TabHomeActivity : Fragment() {
val itemList = ArrayList<HomeCards>()
lateinit var adapter: HomeCardsAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var binding = FragmentTabHomeActivityBinding.inflate(layoutInflater)
adapter = HomeCardsAdapter()
var rv = binding.rvHomeCards
rv.adapter = adapter
loadData()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.cards_home, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
private fun loadData() {
ApiManager.getInstance().service.listHeroes()
.enqueue(object : Callback<ResponseData<List<HomeCards>>> {
override fun onResponse(
call: Call<ResponseData<List<HomeCards>>>,
response: Response<ResponseData<List<HomeCards>>>
) {
val listData: List<HomeCards> = response.body()!!.data
// updating data from network to adapter
itemList.clear()
itemList.addAll(listData)
adapter.updateData(itemList)
adapter.notifyDataSetChanged()
}
override fun onFailure(call: Call<ResponseData<List<HomeCards>>>, t: Throwable) {
}
})
}
}
The HTTP request:
data class ResponseData<T> (
val code: Int,
val data: T
)
interface HomeJsonApiService {
#GET("marvel-heroes.asp?h=2")
fun listHeroes(): retrofit2.Call<ResponseData<List<HomeCards>>>
}
class ApiManager {
private var apiService: HomeJsonApiService? = null
init {
createService()
}
val service: HomeJsonApiService get() = apiService!!
private fun createService() {
val loggingInterceptor =
HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger {
override fun log(message: String) {
Log.i("Retrofit", message)
}
})
loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient.Builder()
.readTimeout(30, TimeUnit.SECONDS)
.connectTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.addInterceptor(loggingInterceptor)
.build()
val retrofit: Retrofit = Retrofit.Builder()
.client(client)
.baseUrl("https://www.mywebsite.com/jsonfolder/JSON/")
.addConverterFactory(GsonConverterFactory.create())
.build()
apiService = retrofit.create(HomeJsonApiService::class.java)
}
companion object {
private var instance: ApiManager? = null
fun getInstance(): ApiManager {
return instance ?: synchronized(this) {
ApiManager().also { instance = it }
}
}
}
}
And my adapter:
class HomeCardsAdapter() : RecyclerView.Adapter<HomeCardsAdapter.ViewHolder>() {
private lateinit var itemList: List<HomeCards>
lateinit var context: Context
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
context = parent.context
val view = LayoutInflater.from(context).inflate(R.layout.cards_home, parent, false)
return ViewHolder(view)
}
override fun getItemCount(): Int {
return if (::itemList.isInitialized) itemList.size else 0
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind()
}
fun updateData(list: List<HomeCards>) {
itemList = list;
notifyDataSetChanged()
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
//var binding = ActivityMainBinding(layoutInflater(inf))
fun bind() {
val item = itemList.get(adapterPosition)
ViewHolder(itemView).itemView.findViewById<TextView>(R.id.cardHomeTitle).text = item.name
ViewHolder(itemView).itemView.findViewById<TextView>(R.id.cardHomeTitle).text = item.superheroName
Glide.with(context)
.load(item.photo)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.circleCrop()
.into(ViewHolder(itemView).itemView.findViewById<ImageView>(R.id.cardHomeIcon))
}
}
}
class HomeCards {
#SerializedName("superhero_name")
var superheroName: String = ""
var name: String = ""
var photo: String = ""
}
The main problem is:
var binding = FragmentTabHomeActivityBinding.inflate(layoutInflater)
That is inside on onCreate but onCreateView is returning another view inflater.inflate(R.layout.cards_home, container, false)
So you are applying the adapter to a recycler that is on the binding, but the view on the screen is inflated from the layout. Change it to this:
private lateinit var binding: FragmentTabHomeActivityBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {
binding = FragmentTabHomeActivityBinding.inflate(layoutInflater, container, false)
return binding.root
}
And move the code from from onCreate to onViewCreated but make sure to use the lateinit binding
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
adapter = HomeCardsAdapter()
var rv = binding.rvHomeCards
rv.adapter = adapter
loadData()
}
After that there is a problem in your adapter: private lateinit var itemList: List<HomeCards> very specifically List<HomeCards>. The method notifyDataSetChanged doesn't work by changing or updating the reference of the data structure but when the collection is modified. Change it to this:
private val list = mutableListOf<HomeCards>()
override fun getItemCount(): Int {
return list.size()
}
fun updateData(list: List<HomeCards>) {
this.itemList.clear()
this.itemList.addAll(list)
notifyDataSetChanged()
}
If onResponse() gets called and provides response, verify that code updating UI is running on main/ui thread. Common source of issue when working with network (other threads).
activity?.runOnUiThread {
itemList.clear()
itemList.addAll(listData)
adapter.updateData(itemList)
adapter.notifyDataSetChanged()
}

fragment cannot be provided without an #Provides-annotated method. Kotlin

My Application class
class MyApp : Application(), HasActivityInjector {
#Inject
lateinit var activityInjector: DispatchingAndroidInjector<Activity>
/*#Inject
lateinit var fragmentInjector: DispatchingAndroidInjector<Fragment>*/
override fun onCreate() {
super.onCreate()
DaggerAppComponent.builder().application(this).build().inject(this)
}
override fun activityInjector(): AndroidInjector<Activity> =
activityInjector
//override fun supportFragmentInjector(): AndroidSupportInjection<Fragment>
= fragmentInjector
}
App Component
#Singleton
#Component(modules = arrayOf(AndroidInjectionModule::class,
AppModule::class, BuilderModule::class))
interface AppComponent {
#Component.Builder
interface Builder {
#BindsInstance
fun application(application: Application): Builder
fun build(): AppComponent
}
fun inject(app: MyApp)
}
App Module
#Module
class AppModule {
#Provides
#Singleton
fun provideUtil(application: Application): Utils = Utils(application)
}
Builder Module
#Module
abstract class BuilderModule {
#ContributesAndroidInjector
abstract fun contributeMainActivity(): MainActivity
#ContributesAndroidInjector
abstract fun contributeHomeFragment(): HomeFragment
}
Main Activity
class MainActivity : AppCompatActivity(), HasSupportFragmentInjector {
#Inject
lateinit var fragmentInjector: DispatchingAndroidInjector<Fragment>
override fun supportFragmentInjector(): AndroidInjector<Fragment> =
fragmentInjector
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this); // Call before super!
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
replaceFragment(HomeFragment())
}
fun replaceFragment(fragment: Fragment) {
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.frameContainer, fragment)
transaction.addToBackStack(null)
transaction.commit()
}
}
Home Fragment
class HomeFragment : Fragment() {
#Inject
lateinit var utils: Utils
override fun onAttach(context: Context?) {
AndroidSupportInjection.inject(this) // Providing the dependency
super.onAttach(context)
}
override fun onCreateView(inflater: LayoutInflater, container:
ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_home, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
utils.toaster("Injected")
}
I am getting this error
D:\Workspace\DaggerKotlin\app\build\tmp\kapt3\stubs\debug\com\cvsingh\daggerkotlin\di\AppComponent.java:8: error: [Dagger/MissingBinding] [dagger.android.AndroidInjector.inject(T)] java.util.Map>> cannot be provided without an #Provides-annotated method.
public abstract interface AppComponent {
^
java.util.Map>> is injected at
dagger.android.DispatchingAndroidInjector.(…, injectorFactoriesWithStringKeys)
dagger.android.DispatchingAndroidInjector is injected at
com.cvsingh.daggerkotlin.ui.MainActivity.fragmentInjector
com.cvsingh.daggerkotlin.ui.MainActivity is injected at
dagger.android.AndroidInjector.inject(T)
component path: com.cvsingh.daggerkotlin.di.AppComponent ? com.cvsingh.daggerkotlin.di.BuilderModule_ContributeMainActivity.MainActivitySubcomponent
}
You're doing it wrong with your MyApp class, you should use DaggerApplication to simplify you dagger integration :
class MyApp : DaggerApplication() {
private val applicationInjector = DaggerApplicationComponent.builder()
.application(this)
.build()
override fun applicationInjector() = applicationInjector
}
And for your information you can simplify the same way your activites and fragments using DaggerAppCompatActivity and DaggerFragment
for example your activity could be :
class MainActivity : DaggerAppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
replaceFragment(HomeFragment())
}
fun replaceFragment(fragment: Fragment) {
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.frameContainer, fragment)
transaction.addToBackStack(null)
transaction.commit()
}
}
If you don't want to use DaggerApplication, DaggerAppCompatActivity, etc.. (sometimes you need to extends from another class) then simply copy paste code from DaggerApplication, DaggerAppCompatActivity, etc in your class