android - Kotlin MVVM Room App 无法恢复数据
问题描述
我正在开发一个 Kotlin 应用程序,它将 Room 实现为数据库,并将 Retrofit 实现为 API 连接库。
我猜 RoomObject 已正确添加到数据库中,所以当我尝试恢复数据以打印到屏幕上时,我的适配器不会提升请求数据的 recycleView。
我尝试做的片段是这样的:
日记片段.kt
package com.example.mvvm_retrofit_imagesearchapp.ui.diary
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import com.example.mvvm_retrofit_imagesearchapp.R
import com.example.mvvm_retrofit_imagesearchapp.adapter.diary.AdapterDiary
import com.example.mvvm_retrofit_imagesearchapp.data.UnsplashPhoto
import com.example.mvvm_retrofit_imagesearchapp.databinding.FragmentDiaryBinding
import com.example.mvvm_retrofit_imagesearchapp.room.PhotoDatabase
import com.example.mvvm_retrofit_imagesearchapp.room.RoomRepository
import com.example.mvvm_retrofit_imagesearchapp.room.RoomResponse
import com.google.firebase.auth.FirebaseAuth
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.android.synthetic.main.fragment_diary.*
import kotlinx.coroutines.launch
@AndroidEntryPoint
class DiaryFragment : Fragment(R.layout.fragment_diary), AdapterDiary.OnItemClickListenerDiary{
private lateinit var viewModel: DiaryViewModel
private var _binding: FragmentDiaryBinding? = null
private val binding get() = _binding!!
private lateinit var user: String
private lateinit var mAuth : FirebaseAuth
private var adapter: AdapterDiary? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mAuth = FirebaseAuth.getInstance();
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
_binding = FragmentDiaryBinding.bind(view)
//Para Instanciar el ViewModel, utilizo el Construtor de clase.
viewModel = DiaryViewModel(RoomRepository(context!!, PhotoDatabase.getDatabase(context!!)!!))
//Al Listener le paso una instancia a partir del observer.
//mientras que al listener del BtnRetry, le paso el atributo de clase.
mAuth.addAuthStateListener {
//TODO() Debug to see if the object is null
if(null != it.currentUser){
user = it.currentUser!!.email.toString()
checkUser(user)
}else{
Toast.makeText(context, "User still be null", Toast.LENGTH_LONG).show()
}
}
val btnRetryDiary = binding.btnRetryDiary
btnRetryDiary.setOnClickListener(View.OnClickListener {
user = mAuth.currentUser?.email.toString()
checkUser(user)
})
}
fun checkUser(user:String){
if(user!="null"){
btnRetryDiary.visibility=View.GONE
Toast.makeText(context, "Already Sign in !", Toast.LENGTH_LONG).show()
//TODO() El adapter Detail se queda a null..
val db = PhotoDatabase.getDatabase(context!!)
viewModel.getPhotoUser(user)!!.observe(viewLifecycleOwner){
lifecycleScope.launch {
searchPhoto(db!!, user)
}
}
setHasOptionsMenu(true)
}else{
Toast.makeText(context, "¡¡ User esta a null !!", Toast.LENGTH_LONG).show()
}
}
//TODO("Compila correctamente pero llamada al DAO devuelve un arraylist vacio")
private suspend fun searchPhoto(db: PhotoDatabase, user: String) {
val data = db.photoDao().selectPhoto(user)
//TODO Cargar la imagen a partir de la url.
data.observe(viewLifecycleOwner, Observer {
//Pass List of entities to adapter.
adapter = AdapterDiary(context!!.applicationContext, it, this)
binding.apply {
recycleViewDiary.setHasFixedSize(true)
recycleViewDiary.itemAnimator = null
recycleViewDiary.adapter = adapter
}
})
}
override fun onDestroy() {
super.onDestroy()
_binding = null
}
override fun onItemClick(photo: RoomResponse) {
val action = DiaryFragmentDirections.actionDiaryFragmentToDetailFragment(photo as UnsplashPhoto)
findNavController().navigate(action)
}
}
我的数据类如下:
RoomUnplashPhoto.kt
package com.example.mvvm_retrofit_imagesearchapp.data
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
import com.example.mvvm_retrofit_imagesearchapp.utils.Global
@Entity(tableName= Global.databaseName, indices = [Index(value = ["uid"], unique = true)])
data class RoomUnsplashPhoto(
@PrimaryKey() val id: Int? = null,
var uid: String,
@ColumnInfo(name = "description") var description: String?,
@ColumnInfo(name = "url") var url: String?,
@ColumnInfo(name="user") var user:String?,
)
RoomResponse.kt
package com.example.mvvm_retrofit_imagesearchapp.room
import com.google.gson.annotations.SerializedName
class RoomResponse {
@SerializedName("url")
var url: String? = null
@SerializedName("user")
var user: String? = null
}
最后,我要求用户添加照片的片段是这样的:
细节片段.kt
@AndroidEntryPoint
class DetailFragment : Fragment(R.layout.fragment_detail){
private val args by navArgs<DetailFragmentArgs>()
private var userIdAdd: Int = 0
private lateinit var db : PhotoDatabase
//TODO(Insertar el user llamadno al DAO)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val binding = FragmentDetailBinding.bind(view)
binding.apply {
val photo = args.photo
var room_photo : RoomUnsplashPhoto? = null
try{
room_photo = RoomUnsplashPhoto(0, photo.id!!,photo.description,photo.urls.full, photo.user.name )
}catch (e:NumberFormatException){
Toast.makeText(context, "¡ Falla la conversion !", Toast.LENGTH_LONG).show()
Log.d("NumberFormat", e.toString())
}
Glide.with(this@DetailFragment)
.load(photo.urls.regular)
.error(R.drawable.ic_error)
.override((Target.SIZE_ORIGINAL)/4)
.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(e: GlideException?,model: Any?,target: Target<Drawable>?,isFirstResource: Boolean): Boolean {
progressBar.isVisible = false
return false
}
override fun onResourceReady(resource: Drawable?,model: Any?,target: Target<Drawable>?,dataSource: DataSource?,isFirstResource: Boolean): Boolean {
progressBar.isVisible = false
textviewDesc.isVisible = photo.description != null
textviewCreator.isVisible = true
return false
}
})
.into(imageView)
textviewDesc.text = photo.description
val uri = Uri.parse(photo.user.attributionUrl)
val intent = Intent(Intent.ACTION_VIEW, uri)
//set the listener to Room
val db = context?.let {
Room.databaseBuilder(
it.applicationContext,
PhotoDatabase::class.java, Global.databaseName
).build()
}
btnAdd.setOnClickListener(View.OnClickListener {
//Pruebo a sacar el id del item introducido en un hilo aparte para
// compararlo en un 2º hilo con la respuesta de la insercion que sera el uid.
GlobalScope.launch {
userIdAdd = getUserAdd(db!!, room_photo!!)
}
GlobalScope.launch {
Looper.getMainLooper()
if (room_photo != null) {
var message:String = insertPhoto(room_photo, db)
activity?.runOnUiThread(Runnable {
Toast.makeText(context, message, Toast.LENGTH_LONG).show()
})
}else {
activity?.runOnUiThread(Runnable {
Toast.makeText(context, "El room_photo es null", Toast.LENGTH_LONG)
.show()
})
}
}
})
textviewCreator.apply {
text = "Photo by ${photo.user.name} on Unsplash"
setOnClickListener {
context.startActivity(intent)
}
paint.isUnderlineText = true
}
}
}
private suspend fun getUserAdd(db:PhotoDatabase, room_photo: RoomUnsplashPhoto):Int {
var addedId = 0
withContext(Dispatchers.IO){
addedId = db?.photoDao()?.insertPhoto(room_photo).toInt()
}
return addedId
}
fun insertPhoto(photo: RoomUnsplashPhoto, db: PhotoDatabase?): String {
//Pass all the data to the RoomDatabase.
var message: String = ""
val resp = db?.photoDao()?.insertPhoto(RoomUnsplashPhoto(
0,
photo.uid,
photo.description,
photo.url,
photo.user
))
if (resp != null) {
if(resp.absoluteValue.toInt() === (userIdAdd.absoluteValue)){
message = "Foto añadida correctamente a su diario."
}else{
message = "No se ha podido añadir la foto a su diario"
}
}
return message
}
}
我希望你能提供帮助,如果这样,请提前感谢!
解决方案
推荐阅读
- python - 悬停 image_rgba 散景
- reactjs - 带有 cookie 的 django-rest-knox
- swift - 如果使用模拟器,从 Xcode 和 xcodebuild 运行 xctests 会失败 - dyld:未加载库:@rpath/libswiftSwiftOnoneSupport.dylib 问题 - print()
- javascript - 注册 ServiceWorker 失败
- python - Xgboost:如何在 Dmatrix 中制作一个 CSV 到一个标签
- firebase - 如何解决flutter中的内部错误以使用firebase_auth
- python - 如何在 python turtle 中添加两个或更多按钮
- mysql - DROP CONSTRAINT 无法找到约束
- matlab - 随机脉冲发生器问题
- php - Python Imports 不会在 PHP 中给出输出