Don't understand why I'm getting this error. Any suggestions/guidance would be great - api

package com.example.myapplication
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.myapplication.MainModel
import com.example.myapplication.MovieAdapter
import com.example.myapplication.R
import com.example.myapplication.retrofit.ApiService
import kotlinx.android.synthetic.main.activity_detail.*
import kotlinx.android.synthetic.main.activity_main.*
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class MainActivity : AppCompatActivity() {
private val TAG: String = "MainActivity"
private lateinit var movieAdapter: MovieAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportActionBar!!.title = "Avengers"
setupRecyclerView()
getDataFromApi()
}
private fun getDataFromApi() {
showLoading(true)
ApiService.endpoint.data()
.enqueue(object : Callback<MainModel> {
override fun onFailure(call: Call<MainModel>, t: Throwable) {
printLog(t.toString())
showLoading(false)
}
override fun onResponse(
call: Call<MainModel>,
response: Response<MainModel>
) {
showLoading(false)
if (response.isSuccessful) {
showResult(response.body()!!)
}
}
})
}
private fun printLog(message: String) {
Log.d(TAG, message)
}
private fun showLoading(loading: Boolean) {
when (loading) {
true -> progressBar.visibility = View.VISIBLE
false -> progressBar.visibility = View.GONE
}
}
private fun showResult(results: MainModel) {
for (result in results.result) printLog("title: ${result.artistId}")
movieAdapter.setData(results.result)
}
private fun setupRecyclerView(){
movieAdapter = MovieAdapter(arrayListOf(), object : MovieAdapter.OnAdapterListener {
override fun onClick(result: MainModel.Result) {
recyclerView.apply {
layoutManager = LinearLayoutManager(context)
adapter = movieAdapter
}
}
})
}
}
This is the error:
2022-08-13 22:41:43.360 14628-14628/com.example.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.myapplication, PID: 14628
java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.Iterator java.util.ArrayList.iterator()' on a null object reference
at com.example.myapplication.MainActivity.showResult(MainActivity.kt:64)
at com.example.myapplication.MainActivity.access$showResult(MainActivity.kt:18)
at com.example.myapplication.MainActivity$getDataFromApi$1.onResponse(MainActivity.kt:46)
at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1.lambda$onResponse$0$retrofit2-DefaultCallAdapterFactory$ExecutorCallbackCall$1(DefaultCallAdapterFactory.java:89)
at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1$$ExternalSyntheticLambda1.run(Unknown Source:6)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

Related

Room data doesn't appear in activity RecyclerView

I am simply trying to setup the ClickListener for changing the user name. Google's tutorials emphasize fragments, which for the moment feels like overkill.
The app crashes when I navigate to the ManageUsers activity. Based on what I've seen in other examples and the Android documentation, I thought I had the View Binding set up properly.
UserListAdapter.kt
package com.neillbarrett.debitsandcredits
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.neillbarrett.debitsandcredits.database.UsersTable
import com.neillbarrett.debitsandcredits.databinding.ActivityManageUsersBinding
class UserListAdapter(private val userSelect: (UsersTable?) -> Unit) :
ListAdapter<UsersTable, UserListAdapter.UserViewHolder>(UsersComparator()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserListAdapter.UserViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.activity_manage_users, parent, false)
return UserViewHolder.create(parent)
}
override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
val current = getItem(position)
holder.bind(current, userSelect)
}
class UserViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val userView: TextView = itemView.findViewById(R.id.tv_UserName)
// var text: String? = null
fun bind(usersTable: UsersTable?, userSelect: (UsersTable?) -> Unit, text: String = usersTable?.userName.toString()) {
userView.text = text
itemView.setOnClickListener { View.OnClickListener {
/* if (View.) { }*/
val nameSelected = userSelect(usersTable)
//userSelect(usersTable)
//need to assign the result of the clicklistener to the editText
//binding.etEditName.setText(R.layout.activity_list_of_users.toString())
}}
}
companion object {
fun create(parent: ViewGroup) : UserViewHolder {
val view: View = LayoutInflater.from(parent.context)
.inflate(R.layout.activity_manage_users, parent, false)
return UserViewHolder(view)
}
}
}
class UsersComparator : DiffUtil.ItemCallback<UsersTable>() {
override fun areItemsTheSame(oldItem: UsersTable, newItem: UsersTable): Boolean {
return oldItem.userName == newItem.userName
}
override fun areContentsTheSame(oldItem: UsersTable, newItem: UsersTable): Boolean {
return oldItem == newItem
}
}
}
ManageUsers.kt
package com.neillbarrett.debitsandcredits
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.TextUtils
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.neillbarrett.debitsandcredits.database.CreditsAndDebitsApp
import com.neillbarrett.debitsandcredits.database.UsersTable
import com.neillbarrett.debitsandcredits.databinding.ActivityManageUsersBinding
class ManageUsers : AppCompatActivity() {
lateinit var binding: ActivityManageUsersBinding
lateinit var recyclerView: RecyclerView
lateinit var editTextAddUser: EditText
lateinit var editTextChangeUser: EditText
lateinit var newUser: String
var userSelect: ((UsersTable?) -> Unit) = {}
var position: Long = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityManageUsersBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
//setContentView(R.layout.activity_manage_users)
val userViewModel: UserViewModel by viewModels {
UserViewModelFactory((application as CreditsAndDebitsApp).repository)
}
recyclerView = findViewById(R.id.rec_view_userList)
editTextAddUser = findViewById(R.id.et_AddUser)
editTextChangeUser = findViewById(R.id.et_Edit_Name)
val adapter = UserListAdapter(userSelect)
binding.recViewUserList.adapter = adapter
binding.recViewUserList.layoutManager = LinearLayoutManager(this)
//recyclerView.adapter = adapter
//recyclerView.layoutManager = LinearLayoutManager(this)
userViewModel.allUsers.observe(this, Observer() {user ->
user?.let { adapter.submitList(it) }
})
val btnAddUser = findViewById<Button>(R.id.btn_AddUser)
binding.btnAddUser.setOnClickListener {
// btnAddUser.setOnClickListener {
if (TextUtils.isEmpty(editTextAddUser.text)) {
Toast.makeText(this, "User name cannot be empty", Toast.LENGTH_SHORT).show()
} else {
newUser = editTextAddUser.text.toString()
// Log.i("Add user button", "Username put into newUser")
userViewModel.insertUser(UsersTable(0, newUser))
// Toast.makeText(this, "Username added to table", Toast.LENGTH_SHORT).show()
// Log.i("Add user button", "Username added to table")
}
}
val btnChangeUser = findViewById<Button>(R.id.btn_ChangeUserName)
binding.btnChangeUserName.setOnClickListener {
// btnChangeUser.setOnClickListener {
Toast.makeText(this, "Selected position is ${recyclerView.getChildAdapterPosition(it)}", Toast.LENGTH_SHORT).show()
/* if (recyclerView.getChildAdapterPosition(it) == -1) {
Toast.makeText(this, "Select a name.", Toast.LENGTH_SHORT).show()
} else {
if (editTextChangeUser.text.toString() == recyclerView.adapter.toString()) {
Toast.makeText(this, "Name has not been changed.", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this, "Name would have been changed.", Toast.LENGTH_SHORT).show()
val rvItemRecId: Long
rvItemRecId = adapter.getItemId(position.toInt())
userViewModel.updateUser(UsersTable(rvItemRecId.toInt(), adapter.toString()))
}
}*/
}
}
}
UserViewModel.kt
package com.neillbarrett.debitsandcredits
import androidx.lifecycle.*
import com.neillbarrett.debitsandcredits.database.UsersTable
import kotlinx.coroutines.launch
import java.lang.IllegalArgumentException
class UserViewModel(private val repository: UserRepository) : ViewModel() {
// Using LiveData and caching what allWords returns has several benefits:
// - We can put an observer on the data (instead of polling for changes) and only update the
// the UI when the data actually changes.
// - Repository is completely separated from the UI through the ViewModel.
val allUsers: LiveData<List<UsersTable>> = repository.allUsers.asLiveData()
/**
* Launching a new coroutine to insert the data in a non-blocking way
*/
fun insertUser(user: UsersTable) = viewModelScope.launch {
repository.insertUser(user)
//repository.insertUser(usersTable = List<UsersTable>())
//repository.insertUser(UsersTable(0, userName = user.userName))
}
fun updateUser(user: UsersTable) = viewModelScope.launch {
repository.updateUser(user)
}
fun deleteUser(user: UsersTable) = viewModelScope.launch {
repository.deleteUser(user)
}
}
class UserViewModelFactory(private val repository: UserRepository) : ViewModelProvider.Factory{
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(UserViewModel::class.java)) {
#Suppress("UNCHECKED_CAST")
return UserViewModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
The LogCat shows this:
2022-11-25 11:43:59.427 8217-8217/com.neillbarrett.debitsandcredits E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.neillbarrett.debitsandcredits, PID: 8217
java.lang.NullPointerException: itemView.findViewById(R.id.tv_UserName) must not be null
at com.neillbarrett.debitsandcredits.UserListAdapter$UserViewHolder.<init>(UserListAdapter.kt:30)
at com.neillbarrett.debitsandcredits.UserListAdapter$UserViewHolder$Companion.create(UserListAdapter.kt:51)
at com.neillbarrett.debitsandcredits.UserListAdapter.onCreateViewHolder(UserListAdapter.kt:21)
at com.neillbarrett.debitsandcredits.UserListAdapter.onCreateViewHolder(UserListAdapter.kt:15)
at androidx.recyclerview.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:7078)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6235)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
at androidx.recyclerview.widget.RecyclerView.onMeasure(RecyclerView.java:3540)
at android.view.View.measure(View.java:26411)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7845)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
at android.view.View.measure(View.java:26411)
at androidx.constraintlayout.widget.ConstraintLayout$Measurer.measure(ConstraintLayout.java:811)
at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.measure(BasicMeasure.java:466)
at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.measureChildren(BasicMeasure.java:134)
at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solverMeasure(BasicMeasure.java:278)
at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:120)
at androidx.constraintlayout.widget.ConstraintLayout.resolveSystem(ConstraintLayout.java:1594)
at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1708)
at android.view.View.measure(View.java:26411)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7845)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:145)
at android.view.View.measure(View.java:26411)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7845)
at androidx.appcompat.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:496)
at android.view.View.measure(View.java:26411)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7845)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at android.view.View.measure(View.java:26411)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7845)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
at android.view.View.measure(View.java:26411)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7845)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at com.android.internal.policy.DecorView.onMeasure(DecorView.java:1050)
at android.view.View.measure(View.java:26411)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:3635)
It's clear I'm missing something, but I have no idea what.

Kotlin: lateinit var needs to be initialized

I'm struggling with both a dilemma and an issue here. The dilemma is that I want to keep the ManagerUsers screen simple, but Google is pushing fragments. I can see a use for fragments for this screen later on, but for now, it seems like overkill. Should I use them anyway?
Second, if I do avoid fragments for now, I am struggling to finish setting up the ClickListener to simply change the name of the user in the ListView. Kotlin seems to have at least 6 different methods for doing most things, making it confusing to figure this out. Google's tutorials force you to use fragments, and others' tutorials don't really cover what I'm trying to do. When I navigate to the Manage Users activity, the app crashes. LogCat shows that userSelect needs to be initialized. I have no idea how to do that.
UserListAdapter.kt
package com.neillbarrett.debitsandcredits
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.neillbarrett.debitsandcredits.database.UsersTable
import com.neillbarrett.debitsandcredits.databinding.ActivityManageUsersBinding
class UserListAdapter(private val userSelect: (UsersTable?) -> Unit) :
ListAdapter<UsersTable, UserListAdapter.UserViewHolder>(UsersComparator()) {
override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
val current = getItem(position)
holder.bind(current, userSelect)
}
class UserViewHolder(private val binding: ActivityManageUsersBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(usersTable: UsersTable?, userSelect: (UsersTable?) -> Unit) {
binding.root.setOnClickListener( View.OnClickListener {
userSelect(usersTable)
binding.etEditName.setText(R.layout.activity_list_of_users.toString())
})
}
companion object {
fun create(parent: ViewGroup) : UserViewHolder {
val view: View = LayoutInflater.from(parent.context)
.inflate(R.layout.activity_manage_users, parent, false)
return UserViewHolder(ActivityManageUsersBinding.bind(view))
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.activity_manage_users, parent, false)
return UserViewHolder.create(parent)
}
class UsersComparator : DiffUtil.ItemCallback<UsersTable>() {
override fun areItemsTheSame(oldItem: UsersTable, newItem: UsersTable): Boolean {
return oldItem == newItem
}
override fun areContentsTheSame(oldItem: UsersTable, newItem: UsersTable): Boolean {
return oldItem.userName == newItem.userName
}
}
}
ManageUsers.kt
package com.neillbarrett.debitsandcredits
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.TextUtils
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.neillbarrett.debitsandcredits.database.CreditsAndDebitsApp
import com.neillbarrett.debitsandcredits.database.UsersTable
import com.neillbarrett.debitsandcredits.databinding.ActivityManageUsersBinding
class ManageUsers : AppCompatActivity() {
lateinit var binding: ActivityManageUsersBinding
lateinit var recyclerView: RecyclerView
lateinit var editTextAddUser: EditText
lateinit var editTextChangeUser: EditText
lateinit var newUser: String
lateinit var userSelect: ((UsersTable?) -> Unit)
var position: Long = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityManageUsersBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
//setContentView(R.layout.activity_manage_users)
val userViewModel: UserViewModel by viewModels {
UserViewModelFactory((application as CreditsAndDebitsApp).repository)
}
recyclerView = findViewById(R.id.rec_view_userList)
editTextAddUser = findViewById(R.id.et_UserName)
editTextChangeUser = findViewById(R.id.et_Edit_Name)
val adapter = UserListAdapter(userSelect)
binding.recViewUserList.adapter = adapter
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(this)
userViewModel.allUsers.observe(this, Observer() {user ->
user?.let { adapter.submitList(it) }
})
val btnAddUser = findViewById<Button>(R.id.btn_AddUser)
btnAddUser.setOnClickListener {
if (TextUtils.isEmpty(editTextAddUser.text)) {
Toast.makeText(this, "User name cannot be empty", Toast.LENGTH_SHORT).show()
} else {
newUser = editTextAddUser.text.toString()
userViewModel.insertUser(UsersTable(0, newUser))
}
}
val btnChangeUser = findViewById<Button>(R.id.btn_ChangeUserName)
btnChangeUser.setOnClickListener {
if (recyclerView.getChildAdapterPosition(it) == -1) {
Toast.makeText(this, "Select a name.", Toast.LENGTH_SHORT).show()
} else {
if (editTextChangeUser.text.toString() == recyclerView.adapter.toString()) {
Toast.makeText(this, "Name has not been changed.", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this, "Name would have been changed.", Toast.LENGTH_SHORT).show()
/*val rvItemRecId: Long
rvItemRecId = adapter.getItemId(position.toInt())
userViewModel.updateUser(UsersTable(rvItemRecId.toInt(), adapter.toString()))*/
}
}
}
}
}
UserViewModel.kt
package com.neillbarrett.debitsandcredits
import androidx.lifecycle.*
import com.neillbarrett.debitsandcredits.database.UsersTable
import kotlinx.coroutines.launch
import java.lang.IllegalArgumentException
class UserViewModel(private val repository: UserRepository) : ViewModel() {
val allUsers: LiveData<List<UsersTable>> = repository.allUsers.asLiveData()
fun insertUser(user: UsersTable) = viewModelScope.launch {
repository.insertUser(user)
}
fun updateUser(user: UsersTable) = viewModelScope.launch {
repository.updateUser(user)
}
fun deleteUser(user: UsersTable) = viewModelScope.launch {
repository.deleteUser(user)
}
}
class UserViewModelFactory(private val repository: UserRepository) : ViewModelProvider.Factory{
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(UserViewModel::class.java)) {
#Suppress("UNCHECKED_CAST")
return UserViewModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
If you check your ManageUsers activity implementation
lateinit var userSelect: ((UsersTable?) -> Unit)
userSelect is lateinit and it must be initialised before you pass the reference to UserListAdapter adapter. Something like this
userSelect = {
// do something
}
before passing to adapter, or
val userSelect: ((UsersTable?) -> Unit) = {
}
at the time of declaration.

How to fix Type mismatch: inferred type is NoteAdapter but () -> ViewModelStore was expected on Android Kotlin

I'm trying to compile an android project but I have this problem at the viewModel level: Type mismatch: inferred type is NoteAdapter but () -> ViewModelStore was expected
Here is the code, This is Kotlin code :
package com.example.roomdatabasetest.adapter
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.widget.doOnTextChanged
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStoreOwner
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.recyclerview.widget.AsyncListDiffer
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.example.roomdatabasetest.MainViewModel
import com.example.roomdatabasetest.database.NoteEntity
import com.example.roomdatabasetest.databinding.ItemNoteBinding
import com.example.roomdatabasetest.ui.MainFragmentDirections
import com.example.roomdatabasetest.ui.UpdateNoteFragment
import com.example.roomdatabasetest.utils.Constants.bundle_note_id
class NoteAdapter : RecyclerView.Adapter<NoteAdapter.ViewHolder>(){
private lateinit var binding: ItemNoteBinding
private lateinit var context: Context
private lateinit var viewModel : MainViewModel
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NoteAdapter.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
binding = ItemNoteBinding.inflate(inflater, parent, false)
context = parent.context
return ViewHolder()
}
override fun onBindViewHolder(holder: NoteAdapter.ViewHolder, position: Int) {
holder.bind(differ.currentList[position])
}
override fun getItemCount(): Int {
return differ.currentList.size
}
inner class ViewHolder : RecyclerView.ViewHolder(binding.root) {
#SuppressLint("SetTextI18n")
fun bind(item: NoteEntity) {
//InitView
binding.apply {
//Set text
tvTitle.text = item.noteTitle
tvDesc.text= item.noteDesc
/*root.setOnClickListener {
val intent = Intent(context,UpdateNoteFragment::class.java)
intent.putExtra(bundle_note_id, item.noteId)
context.startActivity(intent)
}*/
binding.tvTitle.doOnTextChanged { text, start, before, count ->
}
}
}
}
private val differCallback = object : DiffUtil.ItemCallback<NoteEntity>() {
override fun areItemsTheSame(oldItem: NoteEntity, newItem: NoteEntity): Boolean {
return oldItem.noteId == newItem.noteId
}
override fun areContentsTheSame(oldItem: NoteEntity, newItem: NoteEntity): Boolean {
return oldItem == newItem
}
}
val differ = AsyncListDiffer(this, differCallback)
}
I get this error at the end:
e: /home/uriel/AndroidStudioProjects/RoomDatabaseTest/app/src/main/java/com/example/roomdatabasetest/adapter/NoteAdapter.kt: (32, 39): Type mismatch: inferred type is NoteAdapter but ViewModelStoreOwner was expecte
How to solve the problem ?

How can I use notification on Fragment?

I want to use notification on Fragment. And if I touch button, notification will appear.
I use many ways, and I find one way to use it. but it is not worked. only run like this
2022-06-08 15:30:10.765 28876-28876/com.ebookfrenzy.sample D/MyFragment: startMyService: Intent: Intent { cmp=com.ebookfrenzy.sample/.ui.MyService }
And below one is mainFragment.kt
package com.ebookfrenzy.sample.ui.main
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.ebookfrenzy.sample.databinding.FragmentMainBinding
import com.ebookfrenzy.sample.ui.MyService
class MainFragment : Fragment() {
private var _binding: FragmentMainBinding? = null
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
companion object {
fun newInstance() = MainFragment()
private const val TAG = "MyFragment"
}
private lateinit var viewModel: MainViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentMainBinding.inflate(inflater, container, false)
binding.button.setOnClickListener { startMyService()
}
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
private fun startMyService() {
Intent(context, MyService::class.java).also {
Log.d(TAG, "startMyService: Intent: $it")
// Check Android Policy
context?.startForegroundService(it)
// Less than Android Oreo
context?.startService(it)
}
}
}
MyService
package com.ebookfrenzy.sample.ui
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import androidx.annotation.Nullable
import androidx.core.app.NotificationCompat
import com.ebookfrenzy.sample.BuildConfig
import com.ebookfrenzy.sample.R
class MyService : Service() {
companion object {
private const val TAG = "MyService"
}
private val FOREGROUND_ID: Int = 290348
private val foregroundNotificationBuilder: NotificationCompat.Builder
get() = NotificationCompat.Builder(this, applicationContext.packageName).
setSmallIcon(R.mipmap.ic_launcher_round).
setContentTitle("title").
setContentText("content text").
setPriority(NotificationCompat.PRIORITY_HIGH)
override fun onCreate() {
super.onCreate()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
startForegroundService()
return START_STICKY
}
#Nullable
override fun onBind(p0: Intent?): IBinder? {
return null
}
override fun onDestroy() {
super.onDestroy()
stopForeground(true)
}
private fun createNotificationChannel() {
val channelId = applicationContext.packageName
val channelName = BuildConfig.APPLICATION_ID
val channel = NotificationChannel(
channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT
)
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager.createNotificationChannel(channel)
}
private fun startForegroundService() {
val notification = foregroundNotificationBuilder.build()
// when Over android oreo, need to notification channel.
createNotificationChannel()
startForeground(FOREGROUND_ID, notification)
}
}
And other codes are not corrected after created
I want to resolve this problem. Please help me...

Kotlin: java.lang.RuntimeException: Cannot create an instance of class ViewModel

This is my first project using Kotlin, so I'm practice to create an app and using architecture components Room Database, Android View Model and LiveData, but I got this error message.
And the mobile crash unexpectedly,
I don't know how to solve it.
Thanks.
The build.gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: "kotlin-kapt"
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.leaf76.architectureexample"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
def lifecycle_version = "2.2.0"
def room_version = "2.2.5"
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
// com.android.support.cardview => androidx
implementation "androidx.cardview:cardview:1.0.0"
// com.android.support.design => androidx
implementation "com.google.android.material:material:1.0.0"
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
// Annotation processor
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
// Room
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
}
Error message
2020-03-27 02:50:27.987 12708-12708/com.leaf76.architectureexample E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.leaf76.architectureexample, PID: 12708
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.leaf76.architectureexample/com.leaf76.architectureexample.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.leaf76.architectureexample.NoteViewModel
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3448)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2147)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:7811)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1076)
Caused by: java.lang.RuntimeException: Cannot create an instance of class com.leaf76.architectureexample.NoteViewModel
at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:221)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
at com.leaf76.architectureexample.MainActivity.onCreate(MainActivity.kt:21)
at android.app.Activity.performCreate(Activity.java:7955)
at android.app.Activity.performCreate(Activity.java:7944)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3423)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595) 
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2147) 
at android.os.Handler.dispatchMessage(Handler.java:107) 
at android.os.Looper.loop(Looper.java:237) 
at android.app.ActivityThread.main(ActivityThread.java:7811) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1076) 
Caused by: java.lang.InstantiationException: java.lang.Class<com.leaf76.architectureexample.NoteViewModel> has no zero argument constructor
at java.lang.Class.newInstance(Native Method)
at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:219)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187) 
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150) 
at com.leaf76.architectureexample.MainActivity.onCreate(MainActivity.kt:21) 
at android.app.Activity.performCreate(Activity.java:7955) 
at android.app.Activity.performCreate(Activity.java:7944) 
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307) 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3423) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595) 
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2147) 
at android.os.Handler.dispatchMessage(Handler.java:107) 
at android.os.Looper.loop(Looper.java:237) 
at android.app.ActivityThread.main(ActivityThread.java:7811) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1076) 
Note.kt
package com.leaf76.architectureexample
import androidx.room.Entity
import androidx.room.PrimaryKey
#Entity(tableName = "note_table")
data class Note(var title: String, var description: String, var priorty: Int) {
#PrimaryKey(autoGenerate = true)
var Id: Int = 0
}
NoteDatabase
package com.leaf76.architectureexample
import android.content.Context
import android.os.AsyncTask
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.sqlite.db.SupportSQLiteDatabase
#Database(entities = [Note::class], version = 1, exportSchema = false)
abstract class NoteDatabase : RoomDatabase() {
abstract fun noteDao(): NoteDao
// static parameters
companion object {
private lateinit var instance: NoteDatabase
fun getInstance(context: Context): NoteDatabase {
if (instance == null) {
synchronized(NoteDatabase::class.java) {
instance = Room.databaseBuilder(
context.applicationContext,
NoteDatabase::class.java, "note_database"
)
.fallbackToDestructiveMigration()
.addCallback(roomCallbackL)
.build()
}
}
return instance
}
private val roomCallbackL: Callback = object : Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
PopulateDbAsyncTask(instance).execute()
}
}
private class PopulateDbAsyncTask(db: NoteDatabase) : AsyncTask<Void, Void, Void>() {
private val noteDao: NoteDao = db.noteDao()
override fun doInBackground(vararg voids: Void): Void? {
noteDao.insert(Note("Title1", "Description1", 1))
noteDao.insert(Note("Title2", "Description2", 2))
noteDao.insert(Note("Title3", "Description3", 3))
return null
}
}
}
}
NoteRepository
package com.leaf76.architectureexample
import android.app.Application
import android.os.AsyncTask
import androidx.lifecycle.LiveData
class NoteRepository(application: Application) {
// The lateinit avoid Nullable
private var noteDao: NoteDao
private var allNotes: LiveData<List<Note>>
init {
val database = NoteDatabase.getInstance(application.applicationContext)
noteDao = database.noteDao()
allNotes = noteDao.getAllNotes()
}
fun insert(note: Note) {
InsertNoteAsyncTask(noteDao).execute(note)
}
fun update(note: Note) {
UpdateNoteAsyncTask(noteDao).execute(note)
}
fun delete(note: Note) {
DeleteNoteAsyncTask(noteDao).execute(note)
}
fun deleteAllnotes() {
DeleteAllNotesAsyncTask(noteDao).execute()
}
fun getAllNotes(): LiveData<List<Note>> {
return allNotes
}
companion object {
// Insert note
private class InsertNoteAsyncTask(var noteDao: NoteDao) :
AsyncTask<Note, Void, Void>() {
override fun doInBackground(vararg notes: Note): Void? {
noteDao.insert(notes[0])
return null
}
}
// Update note
private class UpdateNoteAsyncTask(var noteDao: NoteDao) :
AsyncTask<Note, Void, Void>() {
override fun doInBackground(vararg notes: Note): Void? {
noteDao.update(notes[0])
return null
}
}
// Delete note
private class DeleteNoteAsyncTask(var noteDao: NoteDao) :
AsyncTask<Note, Void, Void>() {
override fun doInBackground(vararg notes: Note): Void? {
noteDao.delete(notes[0])
return null
}
}
// Delete all note
private class DeleteAllNotesAsyncTask(var noteDao: NoteDao) :
AsyncTask<Void, Void, Void>() {
override fun doInBackground(vararg voids: Void): Void? {
noteDao.deleteAllNotes()
return null
}
}
}
}
NoteViewModel
package com.leaf76.architectureexample
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
class NoteViewModel(application: Application) : AndroidViewModel(application) {
private var repository: NoteRepository = NoteRepository(application)
private var allNotes: LiveData<List<Note>> = repository.getAllNotes()
fun insert(note: Note){
repository.insert(note)
}
fun update(note:Note){
repository.update(note)
}
fun delete(note: Note){
repository.delete(note)
}
fun deleteAllNotes(){
repository.deleteAllnotes()
}
fun getAllNotes(): LiveData<List<Note>>{
return allNotes
}
}
MainActivity
package com.leaf76.architectureexample
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
class MainActivity : AppCompatActivity() {
private val TAG: String = "MainActivity"
private lateinit var noteViewModel: NoteViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.i(TAG,"MainActivity entry on create")
noteViewModel = ViewModelProvider(this).get(NoteViewModel::class.java)
Log.i(TAG,"Get note view model")
noteViewModel.getAllNotes().observe(this, Observer<List<Note>> {
Toast.makeText(this,"onChanged",Toast.LENGTH_LONG).show()
})
Log.i(TAG, "Get Toast")
}
}
It works!!!
When I remove this instance==null condition, but I still don't know kotlin how to run it on Singleton pattern.
// static parameters
companion object {
private lateinit var instance: NoteDatabase
fun getInstance(context: Context): NoteDatabase {
if (instance == null) {
synchronized(NoteDatabase::class.java) {
instance = Room.databaseBuilder(
context.applicationContext,
NoteDatabase::class.java, "note_database"
)
.fallbackToDestructiveMigration()
.addCallback(roomCallbackL)
.build()
}
}
return instance
}
to
// static parameters
companion object {
private lateinit var instance: NoteDatabase
fun getInstance(context: Context): NoteDatabase {
synchronized(NoteDatabase::class.java) {
instance = Room.databaseBuilder(
context.applicationContext,
NoteDatabase::class.java, "note_database"
)
.fallbackToDestructiveMigration()
.addCallback(roomCallbackL)
.build()
}
return instance
}