Activity has no zero argument constructor - Dagger Hilt - android-studio

I am using Dagger Hilt for dependecy Injection
I have a class -
SessionManager
class SessionManager (context: Context){
private val dataStore: DataStore<Preferences> = context.createDataStore(
name = "session"
)
companion object{
val IS_LOGIN = preferencesKey<Boolean>(name = "is_login")
}
suspend fun setLogin(isLogin: Boolean){
dataStore.edit {
preferences ->
preferences[IS_LOGIN] = isLogin
}
}
}
I am trying to call the setLogin func in an activity like this -
MainActivity
#AndroidEntryPoint
class MainActivity #Inject constructor(private val sessionManager: SessionManager) :
AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
lifecycleScope.launch {
sessionManager.setLogin(true)
}
}
MyApplication
#HiltAndroidApp
class MyApplication : Application() {
}
Manifest
<application
android:name=".MyApplication"
android:allowBackup="true"/>
As you can see, I have used the #AndroidEntryPoint Annotation but I still get this runtime error
*java.lang.Class<com.app.app.activities.MainActivity> has no zero argument constructor*

For MainActivity I think you cannot do contructor injection, so try field injection as:
#AndroidEntryPoint
class MainActivity : AppCompatActivity() {
#Inject
lateinit var sessionManager: SessionManager
override fun onCreate(savedInstanceState: Bundle?) {
lifecycleScope.launch {
sessionManager.setLogin(true)
}
}
}
Now you should be able to use sessionManager inside onCreate

Related

ViewModelProvider not taking "this" (MainActivity) as its owner in kotlin Android Studios

I am trying to communicate between MainActivity.kt and sharedviewmodel.kt which is of type viewModel() for WearOS, But when i try to create an instance of the sharedviewmodel.kt in MainActivity.kt by below lines
private lateinit var viewModel: sharedviewmodel
viewModel = ViewModelProvider(this).get(sharedviewmodel::class.java)
when i pass "this" as owner of the ViewModelProvider, i face a error called
Required : ViewModelStoreOwner
Found : MainActivity
Kindly someone help to solve the issue,
Find the MainActivity.kt and sharedviewmodel.kt below.
import android.app.Activity
import android.os.Bundle
import android.util.Log
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.example.watch7_view_model_example.databinding.ActivityMainBinding
class MainActivity : Activity() {
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel: sharedviewmodel
var tag = "view_model"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
viewModel = ViewModelProvider(this).get(sharedviewmodel::class.java)
viewModel.azimuth().observe(this, Observer {
Log.d(tag,"data")
})
}
}
sharedviewmodel.kt
package com.example.watch7_view_model_example
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class sharedviewmodel:ViewModel() {
private val azimuth: MutableLiveData<String> = MutableLiveData()
private val elevation: MutableLiveData<String> = MutableLiveData()
fun azimuth(): LiveData<String> = azimuth
fun elevation(): LiveData<String> = elevation
fun azimuth(azimuth_t: String) {
azimuth.value = azimuth_t
}
fun elevation(elevation_t: String) {
elevation.value = elevation_t
}
init {
// Setting default value
azimuth.value = "0"
elevation.value = "0"
}
}`

Confused about inheriting RecyclerView.Adapter and RecyclerView.ViewHolder abstract classes (Kotlin/Android Studio)

I am confused about the inheritance of the RecyclerView.Adapter and RecyclerView.ViewHolder abstract classes. In the code below I inherited the abstract class RecyclerView.Adapter, hence I had to override the fun onCreateViewHolder, fun onBindViewHolder and fun getItemCount. I understand that part, however, why am I not required to override the abstract class RecyclerView.ViewHolder(view) as well?
I don't fully understand the explanation from the android studio docs.
class ItemAdapter(
private val context: Context,
private val dataset: List<Affirmation>
) : RecyclerView.Adapter<ItemAdapter.ItemViewHolder>() {
class ItemViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
val textView: TextView = view.findViewById(R.id.item_title)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
// create a new view
val adapterLayout = LayoutInflater.from(parent.context)
.inflate(R.layout.list_item, parent, false)
return ItemViewHolder(adapterLayout)
}
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
val item = dataset[position]
holder.textView.text = context.resources.getString(item.stringResourceId)
}
override fun getItemCount() = dataset.size

E/RecyclerView: No adapter attached; skipping layout(Kotlin)

I have a trouble with a error "E/RecyclerView: No adapter attached; skipping layout" for 2 days...
Please help me what causes this error...
I already checked that getItemCount function return 1 result(Because the ProductEntity database only have 1 data)
Thank you in advance!!
[ProductActivity.kt]
package com.example.trymakeapp
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.trymakeapp.databinding.ActivityProductBinding
import com.example.trymakeapp.databinding.ItemProductBinding
import com.example.trymakeapp.db.AppDatabase
import com.example.trymakeapp.db.ProductDao
import com.example.trymakeapp.db.ProductEntity
class ProductActivity : AppCompatActivity() {
private lateinit var binding: ActivityProductBinding
private lateinit var db: AppDatabase
private lateinit var productDao: ProductDao
private lateinit var productList : ArrayList<ProductEntity>
private lateinit var adapter : ProductRecyclerViewAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityProductBinding.inflate(layoutInflater)
setContentView(binding.root)
db = AppDatabase.getInstance(this)!!
productDao = db.getProductDao()
getAllProductList()
}
private fun getAllProductList() {
Thread {
productList = ArrayList(productDao.getAll())
setRecyclerView()
}.start()
println("#####")
}
private fun setRecyclerView() {
runOnUiThread {
adapter = ProductRecyclerViewAdapter(productList)
binding.recyclerView.adapter = adapter
binding.recyclerView.layoutManager = LinearLayoutManager(this#ProductActivity)
}
}
}
[ProductRecyclerViewAdapter.kt]
package com.example.trymakeapp
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.trymakeapp.databinding.ItemProductBinding
import com.example.trymakeapp.db.ProductEntity
import java.util.ArrayList
class ProductRecyclerViewAdapter(private val productList : ArrayList<ProductEntity>)
: RecyclerView.Adapter<ProductRecyclerViewAdapter.MyViewHolder>() {
inner class MyViewHolder(binding: ItemProductBinding) :
RecyclerView.ViewHolder(binding.root) {
val product_idx = binding.productIdx
val product_name = binding.productName
val product_price = binding.productPrice
val product_img = binding.productImg
val root = binding.root
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val binding : ItemProductBinding =
ItemProductBinding.inflate(LayoutInflater.from(parent.context),
parent, false)
return MyViewHolder(binding)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val productData = productList[position]
holder.product_idx.text = productData.idx
holder.product_name.text = productData.name
holder.product_price.text = productData.price.toString()
}
override fun getItemCount(): Int {
return productList.size
}
}
[MainActivity.kt]
...
...
btn3.setOnClickListener {
val intent = Intent(this, ProductActivity::class.java)
startActivity(intent)
}
Try to move the initialization in the onCreate method:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityProductBinding.inflate(layoutInflater)
setContentView(binding.root)
db = AppDatabase.getInstance(this)!!
productDao = db.getProductDao()
binding.recyclerView.layoutManager = LinearLayoutManager(this)
adapter = ProductRecyclerViewAdapter(arrayListOf())
binding.recyclerView.adapter = adapter
getAllProductList()
}
And edit your setRecyclerView method like this (You can remove the adapter and productList global variables):
private fun setRecyclerView(productList: ArrayList<ProductEntity>) {
runOnUiThread {
binding.recyclerView.adapter = ProductRecyclerViewAdapter(productList)
}
}
EDIT
To handle the fact that data are not displayed. Try to use LiveData to observe its changes:
#Dao
interface ProductDao {
#Query("select * from ProductEntity")
fun getAll() : LiveData<List<ProductEntity>>
}
Then observe changes in the getAll method using observe:
private fun getAllProductList() {
productDao.getAll().observe(this) {
setRecyclerView(ArrayList(it))
}
}

how to solve this startActivityForResult

how to solve this kind of problem starActivityForResult please any budy guide me to solve this
startActivityForResult is deprecated following is new the way. Here is a full source code example
MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var tvResult:TextView
private lateinit var btnNext:Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tvResult = findViewById(R.id.tv_result)
btnNext = findViewById(R.id.btn_next)
btnNext.setOnClickListener {
openActivityForResult(Intent(this,SampleActivity::class.java))
}
}
private var resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val mIntent: Intent? = result.data
val mDataString = mIntent?.getStringExtra("result_data")
tvResult.text = mDataString
}
}
private fun openActivityForResult(mIntent: Intent) {
resultLauncher.launch(mIntent)
}
}
SampleActivity
class SampleActivity : AppCompatActivity() {
private lateinit var btnDone: Button
private val sampleData = "Sample Activity Result Data"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sample)
btnDone = findViewById(R.id.btn_done)
btnDone.setOnClickListener{
returnForResult()
}
}
private fun returnForResult(){
val replyIntent = Intent()
replyIntent.putExtra(
"result_data",
sampleData
)
setResult(Activity.RESULT_OK, replyIntent)
finish()
}
}
startActivityForResult is deprecated, meaning that it will no longer be supported going forward. That is why Android Studio is showing you the lines through the code. Instead, review this Stackoverflow post on alternative options:
OnActivityResult method is deprecated, what is the alternative?

Interface OnSeekBarChangeListner does not have constructor / No members to implement have been found

[![Not able to implement Menbers`package com.manan.musicx
import android.content.Context
import android.media.AudioManager
import android.media.MediaPlayer
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.provider.MediaStore
import android.widget.Button
import android.widget.MediaController
import android.widget.SeekBar
class MainActivity : AppCompatActivity() {
lateinit var btnPlay: Button
lateinit var btnPause: Button
lateinit var btnStop: Button
lateinit var player: MediaPlayer
lateinit var sbVolume: SeekBar
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btnPlay = findViewById(R.id.btnPlay)
btnPause = findViewById(R.id.btnPause)
btnStop = findViewById(R.id.btnStop)
sbVolume = findViewById(R.id.sbVolume)
val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
player = MediaPlayer.create(this#MainActivity, R.raw.music)
val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
val curVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
sbVolume.setMax(maxVolume)
sbVolume.setProgress(curVolume)
sbVolume.setOnSeekBarChangeListener(SeekBar.OnSeekBarChangeListener())
// Play function, play set on click listner
btnPlay.setOnClickListener {
player.start()
}
// Pause function, pause set on click listner
btnPause.setOnClickListener {
player.pause()
}
// Stop function, stop set on click listner
btnStop.setOnClickListener {
player.stop()
}
}
}`]1]1
You should write the Seekbar.OnSeekBarChangeListener as:
sbVolume.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
//onProgressChanged
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
//onStartTrackingTouch
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
//onStopTrackingTouch
}
})
or create a class implementing SeekBar.OnSeekBarChangeListener as:
private class MySeekbarChangeListener : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
//onProgressChanged
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
//onStartTrackingTouch
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
//onStopTrackingTouch
}
}
and use it as:
sbVolume.setOnSeekBarChangeListener(MySeekbarChangeListener())

Resources