如何在 @Preview @Composable 中初始化视图模型的接口

问题描述 投票:0回答:1

我的问题在于如何初始化要在 @Preview @Composable 函数中使用的视图模型中的接口。由于以下堆栈跟踪,我的预览未显示在 Android Studio 中,当我在模拟器或设备中运行时,我的下一个活动(可组合项)也未显示。

https://1drv.ms/w/s!AnsFOFM6YEPJqKYPTlOnwwfwZ1NNAQ?e=QieFPV

以下代码显示了问题区域:

@Composable
fun WishListViewModelData(fbVM: FirebaseWishListViewModel) {
val fb = Firebase
val loggedInCurrentUserEmail = fb.auth.currentUser?.email.toString()
val loggedInEmail: String = loggedInCurrentUserEmail
val recipState: State<RecipientData> = fbVM.uiRecipientState.collectAsState()
val purchaserState: State<PurchaserData> = fbVM.uiPurchaserState.collectAsState()
RecipientWishList(
    loggedInEmail = loggedInEmail,
    recipState = recipState,
    purchaserState = purchaserState,
    fbVM = fbVM
)

}

@Preview(showBackground = true, apiLevel = 33)
@Composable
fun WishListBody() {
lateinit var contactsRepository: ContactsRepository
val repoContacts = contactsRepository
val viewModel = FirebaseWishListViewModel(repoContacts)
WishListViewModelData(fbVM = viewModel)
}

@SuppressLint("SuspiciousIndentation")
@OptIn(ExperimentalGlideComposeApi::class)
@Composable
fun RecipientWishList(
loggedInEmail: String?,
recipState: State<RecipientData>,
purchaserState: State<PurchaserData>,
fbVM: FirebaseWishListViewModel
) {

val requestManager = Glide.with(LocalContext.current)
val imageFileName: String? = null
val showDialog = remember {mutableStateOf(false)}

var selectedRecipientProfile: MutableMap<String,Any> = mutableMapOf()
val purchaserInfo = purchaserState.value
val purchaserImages = purchaserState.value.purchaserImage?.value!!

Box(
    Modifier
        .wrapContentHeight(Alignment.CenterVertically)
        .wrapContentWidth(Alignment.CenterHorizontally)
)
{
   Column (
        modifier = Modifier
            .fillMaxWidth(1f)
            .fillMaxHeight(1f)

    )
    {
       // Purchaser Icon Button
        Button(
            onClick = { showDialog.value = true },
            modifier = Modifier
                .wrapContentWidth(Alignment.CenterHorizontally)
                .wrapContentHeight(Alignment.CenterVertically),
        ) {
            if (showDialog.value) {

                ShowPopUp(purchaserImages = purchaserImages, fbVM = fbVM)
            }
        }
        // Active recipient picture with gift items
    Row (modifier = Modifier.wrapContentWidth(Alignment.CenterHorizontally)){
        val recipList = fbVM.getAllRecipientsInfo(loggedInEmail)

        SetRecipientImage(recipientMap = recipList, rm = requestManager, imageURL = 
        recipState.value.recipientImage.toString() )
        val productMap: MutableMap<String, String> = mutableMapOf()
        GetListItems(products = productMap)
    }
        //List of all recipients that belongs to signed in user

    LazyRow(state = rememberLazyListState()){

        val numRecipients = fbVM.getAllRecipientsInfo(loggedInEmail.toString()).count()
        items(numRecipients) {
            ElevatedButton(onClick = {
                selectedRecipientProfile =
                    loggedInEmail?.let { it1 -> switchRecipientProfile(it1, 
   fbVM.getAllRecipientsInfo(loggedInEmail)) }!!
            }) {
                GlideImage(model = recipState.value.recipientImage!!, 
     contentDescription = "${recipState.value.recipientFirstName}"
                    .plus("")
                    .plus("${recipState.value.recipientLastName}")
                )
                Text (recipState.value.recipientFirstName.toString())
                Text (recipState.value.recipientLastName.toString())
                Text (recipState.value.recipientAddress.toString())
                Text (recipState.value.recipientCity.toString())
                Text (recipState.value.recipientState.toString())
                Text (recipState.value.recipientZipCode.toString())
                Text (recipState.value.recipientPhone.toString())
                Text (recipState.value.recipientEmail.toString())

            }

        }

    }


   }

}
}

My view model looks like the following:


package com.tritongames.shoppingwishlist.data.viewmodels

import android.util.Log
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.google.firebase.Firebase
import com.google.firebase.auth.auth
import com.google.firebase.firestore.DocumentSnapshot
import com.google.firebase.firestore.firestore
import com.google.firebase.storage.FirebaseStorage
import com.tritongames.shoppingwishlist.data.repository.contacts.ContactsRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.getAndUpdate
import kotlinx.coroutines.launch
import java.io.File
import javax.inject.Inject

data class PurchaserData(
val purchaserImage: MutableState<MutableMap<String, String>>? = null,
val purchaserFirstName: MutableState<String?>? = null,
val purchaserLastName: MutableState<String?>? = null,
val purchaserAddress: MutableState<String?>? = null,
val purchaserCity: MutableState<String?>? = null,
val purchaserState: MutableState<String?>? = null,
val purchaserZipCode: MutableState<String?>? = null,
val purchaserEmail: MutableState<String?>? = null,
val purchaserPhone: MutableState<String?>? = null,
val purchaserPassword: MutableState<String?>? = null,
val purchaserUserName: MutableState<String?>? = null,
)
data class RecipientData(
val recipientImage: MutableState<String?>? = null,
val recipientFirstName: MutableState<String?>? = null,
val recipientLastName: MutableState<String?>? = null,
val recipientAddress: MutableState<String?>? = null,
val recipientCity: MutableState<String?>? = null,
val recipientState: MutableState<String?>? = null,
val recipientZipCode: MutableState<String?>? = null,
val recipientEmail: MutableState<String?>? = null,
val recipientPhone: MutableState<String?>? = null,
val recipientPassword: MutableState<String?>? = null,
val recipientUserName: MutableState<String?>? = null,
 )

  @HiltViewModel
  class FirebaseWishListViewModel @Inject constructor(private val contactsRepository: 
  ContactsRepository) : ViewModel() {


  fun repoContacts(): ContactsRepository {
   return contactsRepository
  }

  private val _uiPurchaserState = MutableStateFlow(PurchaserData())
  val uiPurchaserState: StateFlow<PurchaserData> = _uiPurchaserState.asStateFlow()

  private val _uiRecipientState = MutableStateFlow(RecipientData())
  val uiRecipientState: StateFlow<RecipientData> = _uiRecipientState.asStateFlow()

  companion object {
    @Suppress("UNCHECKED_CAST")
    class FirebaseWishListViewModelFactory(private val contactsRepository: 
  ContactsRepository):
        ViewModelProvider.Factory {

        override fun <T : ViewModel> create(modelClass: Class<T>): T =
            with(modelClass){

                lateinit var vm: T
                when{
                    isAssignableFrom(FirebaseWishListViewModel::class.java) -> 
 FirebaseWishListViewModel(contactsRepository)

                    else -> { throw IllegalArgumentException("Unknown ViewModel class: 
 ${modelClass.name}")}
                }


            } as T

    }
}

fun updateImageFile(imageFilePath: String, email: String) {
    val fb = Firebase.firestore
    val imageUpdateRef = fb.collection("purchasers").document(email)
    imageUpdateRef.update("Image",imageFilePath)


}

fun getAllRecipientsInfo(loggedInEmail: String?): List<DocumentSnapshot> {
    var recipients = listOf<DocumentSnapshot>()
    viewModelScope.launch(Dispatchers.IO) { recipients = loggedInEmail?.let { 
 contactsRepository.getAllRecipients(it) }!!

    }

    return recipients
}
fun getAllPurchaserPictures(loggedInEmail: String): MutableMap<String,String> {
    val purchaserImagesMap: MutableMap<String,String> = mutableMapOf()
    viewModelScope.launch(Dispatchers.IO) {
        val purchPictures = _uiPurchaserState.getAndUpdate {
            val pics = 
  mutableStateOf(contactsRepository.getPurchaserPictures(loggedInEmail))
           PurchaserData(pics)
        }

        purchPictures.purchaserImage?.value?.let { purchaserImagesMap.putAll(it) }


    }
    return purchaserImagesMap


}

fun saveExistingUserImageFiles(images: MutableMap<String,String>, loggedInEmail: 
String?) {
    val fb = Firebase.firestore
    val purchaserReferenceImages = 
 fb.collection("purchasers").document(loggedInEmail.toString())
    for (key in images.keys) {
        purchaserReferenceImages.update("Image", images[key].toString() )
    }


}


fun selectImageDownload(items: MutableMap<String,String>, picName: String): String? {
    var chosenImageFilePath: String? = null
    val fbStorage = FirebaseStorage.getInstance()
    val purchaserImagesReference = 
  fbStorage.reference.child("purchasers/loggedInEmail/Images")
    val localFile = File.createTempFile(items[picName].toString(), "jpg")
    purchaserImagesReference.getFile(localFile)
        .addOnSuccessListener {
            chosenImageFilePath = it.storage.path


        }
        .addOnFailureListener {
            Log.d("FirebaseWishListViewModel", it.message.toString())

        }
    return chosenImageFilePath
}

fun getPurchaserInfo(loggedInEmail: String?): MutableMap<String, String> {
    val purchaserMap: MutableMap<String, String> = mutableMapOf()

    val fbAuthEmail = Firebase.auth.currentUser?.email
    Log.d("FirebaseListViewModel", "Firebase Auth Email: ${fbAuthEmail.toString()}")
    Log.d("FirebaseListViewModel", "Logged in Email: ${loggedInEmail.toString()}")
    if (fbAuthEmail != null && fbAuthEmail == loggedInEmail) {

        val fb = Firebase.firestore
        fb.collection("purchasers")
            .document(loggedInEmail)
            .get()
            .addOnCompleteListener {

                purchaserMap.putAll(it.result.data as MutableMap<String,String>)
            }
            .addOnFailureListener {
                Log.d("Wish List", it.message.toString())
            }
    }


    return purchaserMap
}


}
android viewmodel composable
1个回答
0
投票

就像 documentation 所说的 android 预览有一些限制。

“在可组合项中使用 ViewModel 时,预览受到限制。预览系统无法构造传递给 ViewModel 的所有参数,例如存储库、用例、管理器或类似参数。”

但是,您可以轻松解决这个问题,只需使组件与 ViewModel 对象解耦即可。(文档显示了其他示例)

示例:

@Composable
fun ProfileScreen(viewModel: ProfileViewModel = viewModel()) {
    ProfileScreenContent(
        name = viewModel.name,
        onNameChanged = viewModel::onNameChanged
    )
}

@Composable
fun ProfileScreenContent(name: String, onNameChanged: (name: String) -> Unit) {
    //TODO ...view...
}

@Preview
@Composable
fun ProfileScreenContentPreview() { // And here you can mock whatever you want
    ProfileScreenContent(
        name = "Test",
        onNameChanged = {})
}
© www.soinside.com 2019 - 2024. All rights reserved.