我目前正面临一个错误,在那里的家庭片段和使用viewmodel,recyclerview实现CRUD.错误是,我在登录时使用id和密码在loginfragment,它出现错误,错误说,不能创建类NoteViewModel的示例,我不知道哪里的部分是错误的
这是家庭片段
package com.example.challenge4binar
import android.app.AlertDialog
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.findNavController
import com.example.challenge4binar.databinding.FragmentHomeBinding
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [HomeFragment.newInstance] factory method to
* create an instance of this fragment.
*/
class HomeFragment : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!
private lateinit var sharedPreferences: SharedPreferences
private val noteViewModel: NoteViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
_binding = FragmentHomeBinding.inflate(inflater, container, false)
sharedPreferences = requireContext().getSharedPreferences("myPrefs", Context.MODE_PRIVATE)
return binding.root
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment HomeFragment.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
HomeFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.tvLogout.setOnClickListener {
it.findNavController().navigate(R.id.action_homeFragment_to_loginFragment)
}
val adapter = NoteAdapter(requireContext(), noteViewModel, mutableListOf())
val recyclerView = binding.rvNote
recyclerView.adapter = adapter
noteViewModel.allNotes.observe(viewLifecycleOwner) { notes ->
if (notes.isEmpty()) {
binding.tvDatakosong.visibility = View.VISIBLE
binding.rvNote.visibility = View.GONE
} else {
binding.tvDatakosong.visibility = View.GONE
binding.rvNote.visibility = View.VISIBLE
adapter.setNotes(notes)
}
}
binding.btnTambahHome.setOnClickListener{
dialogtambah()
}
}
fun dialogtambah() {
val builder = AlertDialog.Builder(requireContext())
val inflater = layoutInflater
val dialogView = inflater.inflate(R.layout.tambah, null)
builder.setView(dialogView)
builder.setTitle("Tambah Data")
builder.setPositiveButton("Add") { dialog, _ ->
val contentEditText = dialogView.findViewById<EditText>(R.id.et_judul_tambah)
val titleEditText = dialogView.findViewById<EditText>(R.id.et_catatan_tambah)
val notecontent = contentEditText.text.toString()
val titlenote = titleEditText.text.toString()
if (notecontent.isNotEmpty() && titlenote.isNotEmpty()) {
val newNote = Note(note = notecontent, title = titlenote)
noteViewModel.insert(newNote)
}
}
}
}
字符串
这不是视图模型
package com.example.challenge4binar
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
class NoteViewModel(private val repository: NoteRepository):ViewModel() {
val allNotes: LiveData<List<Note>> =repository.allNotes
fun insert(note: Note) = viewModelScope.launch {
repository.insert(note)
}
fun update(note:Note) = viewModelScope.launch {
repository.update(note)
}
fun delete(note:Note) = viewModelScope.launch {
repository.delete(note)
}
}
型
这是notRepository
package com.example.challenge4binar
import androidx.lifecycle.LiveData
class NoteRepository(private val noteDao: NoteDao) {
val allNotes: LiveData<List<Note>> = noteDao.getAllNotes()
suspend fun insert(note: Note){
noteDao.insert(note)
}
suspend fun update(note:Note){
noteDao.update(note)
}
suspend fun delete (note:Note){
noteDao.delete(note)
}
}
型
这是Note
@Entity(tableName = "notes")
data class Note(
@PrimaryKey(autoGenerate = true)val id:Long = 0,
var title:String,
var note:String
)
型
这不是一个适配器
package com.example.challenge4binar
import android.app.AlertDialog
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView
class NoteAdapter(
private val context: Context,
private val noteViewModel: NoteViewModel,
private val notes: MutableList<Note>):RecyclerView.Adapter<NoteAdapter.ViewHolder>() {
inner class ViewHolder(itemView: View):RecyclerView.ViewHolder(itemView) {
val deleteButton : ImageView = itemView.findViewById(R.id.btn_delete_rv)
val updateButton :ImageView = itemView.findViewById(R.id.btn_update_rv)
fun bind(note: Note){
deleteButton.setOnClickListener{
dialoghapus(note)
}
updateButton.setOnClickListener {
dialogupdate(note)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NoteAdapter.ViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.delete, parent, false)
return ViewHolder(itemView)
}
override fun onBindViewHolder(holder: NoteAdapter.ViewHolder, position: Int) {
val note = notes[position]
holder.bind(note)
}
override fun getItemCount(): Int {
return notes.size
}
private fun dialoghapus(note: Note) {
val builder = AlertDialog.Builder(context)
builder.setTitle("Delete Note")
builder.setPositiveButton("Delete") { dialog, _ ->
noteViewModel.delete(note)
val position = notes.indexOf(note)
if (position != -1) {
notes.removeAt(position)
notifyItemRemoved(position)
}
dialog.dismiss()
}
builder.setNegativeButton("Cancel") { dialog, _ ->
dialog.dismiss()
}
builder.show()
}
private fun dialogupdate(note: Note) {
val builder = AlertDialog.Builder(context)
val inflater = LayoutInflater.from(context)
val dialogView = inflater.inflate(R.layout.update, null)
// Use var instead of val for these variables
var etJudul = dialogView.findViewById<EditText>(R.id.et_judul_edit)
var etCatatan = dialogView.findViewById<EditText>(R.id.et_catatan_edit)
val btnInput = dialogView.findViewById<Button>(R.id.btn_edit)
etJudul.setText(note.title)
etCatatan.setText(note.note)
builder.setView(dialogView)
builder.setTitle("Update Note")
val dialog = builder.create()
btnInput.setOnClickListener {
// Handle the update logic here
val updatedTitle = etJudul.text.toString()
val updatedNote = etCatatan.text.toString()
if (updatedTitle.isNotEmpty() && updatedNote.isNotEmpty()) {
// Update the note with the new data
note.title = updatedTitle
note.note = updatedNote
// Call your update method or ViewModel function here
// For example: noteViewModel.update(note)
// Dismiss the dialog when the update is done
dialog.dismiss()
} else {
// Display an error message or handle empty fields
}
}
dialog.show()
}
fun setNotes(newNotes: List<Note>){
notes.clear()
notes.addAll(newNotes)
}
}
型
2条答案
按热度按时间y0u0uwnf1#
这是因为您将NoteRepository传递给NoteViewModel构造函数,并使用delegate函数示例化片段中的viewModel,因此它不会获得对它的任何引用。
您将需要一个ViewModelFactory,https://developer.android.com/topic/libraries/architecture/viewmodel/viewmodel-factories
更新日期:
NoteRepository
字符串
NoteViewModel
型
NoteViewModelFactory
型
用法:MainActivity
型
让我知道,如果你仍然面临的问题。
更新二:
只需在您的HomeFragment中替换此内容,您将在LogCat中找到日志
型
cnwbcb6i2#
你不能直接将数据传递给viewModel,你必须创建一个viewModelFactory,它将接收数据并为你创建一个ViewModel对象。然后你可以在你的片段或Activity中使用这个viewModel对象。在互联网上有很多关于viewmodel和viewmodel工厂的资源。