my problem lies with how to initialize an interface in a viewmodel that is to be used in a @Preview @Composable function. My preview is not showing up in Android Studio because of the following stack trace nor is my next activity (Composables) when I run in emulator or device.
以下守则显示了问题领域:
@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 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
}
/ 联系人
override suspend fun
getPurchaserPictures(loggedInEmail:
String):
MutableMap<String, String> {
val filePath = StringBuilder()
filePath.append("purchasers/")
.append(loggedInEmail)
.append("/Images")
val storage: FirebaseStorage =
FirebaseStorage.getInstance()
var imageFileNames:
MutableMap<String,String>
storage.reference.child("purchasers/$loggedIn
Email/Images" )
.listAll()
.addOnSuccessListener { it ->
for(item: StorageReference in
it.items) {
val name = item.name
val path = item.path
imageFileNames =
mutableMapOf(name to path)
Log.d("ContactsRepositoryImpl",
imageFileNames.values.toString())
}
}
return imageFileNames
}