Load image from firestore collection into LazyColumn in jetpack compose

Viewed 40

My app has a navigation bar and in one navBarItem I have two tabs, I want to read images and their caption I have stored in my firebase firestore collection into a LazyColumn in one of the tabs. Here is how my DataException and GalleryRepo class looks like

  data class DataOrException<T, E : Exception> (
    var data: T? = null,
    var e: E? = null
        )

    @Singleton
    class GalleryRepo @Inject constructor(
    private val queryImageData: Query
     ) {
    fun getImagesFromFirestore(): DataOrException<List<PQImageGallery>, Exception> {
        val dataOrException = DataOrException<List<PQImageGallery>, Exception>()
        try {
            dataOrException.data = queryImageData.get()
                .result.map { document -> document.toObject(PQImageGallery::class.java) }
        } catch (e: FirebaseFirestoreException) {
            dataOrException.e = e
        }
        return dataOrException
     }
 }

My data class

    data class PQImageGallery (
    var imageUrl: String? =null,
    var caption: String? = null
 )

ViewModels...

@HiltViewModel
class PQViewModel  @Inject constructor(
    private val repository: GalleryRepo
): ViewModel() {
    var loading = mutableStateOf(false)
    val data: MutableState<DataOrException<List<PQImageGallery>, Exception>> = mutableStateOf(
        DataOrException(
            listOf(),
            Exception("")
        )
    )

    init {
        getGalleryCollection()
    }

    private fun getGalleryCollection() {
        viewModelScope.launch {
            loading.value = true
            data.value = repository.getImagesFromFirestore()
            loading.value = false
        }
    }
    }


@Module
@InstallIn(SingletonComponent::class)
object RemoteImageModel {
    @Provides
    @Singleton
    fun loadImagesInCollection() = FirebaseFirestore.getInstance()
        .collection(IMAGE_COLLECTION)
}

My GalleryCollection composable file

@Composable
fun GalleryCollection(dataOrException: DataOrException<List<PQImageGallery>, Exception>) {
    val images = dataOrException.data
    images?.let {
        LazyColumn {
            items(items = images) { product ->
                GalleryCard(pqImageGallery = product)
            }
        }
    }
    val e = dataOrException.e
    e?.let {
        Text(
            text = e.message!!,
            modifier = Modifier.padding(16.dp)
        )
    }  
  }

@Composable
fun GalleryCard(
    pqImageGallery: PQImageGallery,
) {
    Card(...) {
        Box(modifier = Modifier
            .fillMaxSize()

        ) {
            pqImageGallery.imageUrl?.let { imageUrl ->
                CoilImage(
                    data = imageUrl,
                    ....
                )
            }

            pqImageGallery.caption?.let { caption ->
                Text(
                    text = caption,
                    ...
                )
            }
        }

    }
}

My navBarItem that contains the two tabs called Home

class Home : ComponentActivity() {
    private val viewModel: PQViewModel by viewModels()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            HomeScreen(viewModel)
        }
    }
}


@Composable
fun HomeScreen(
    viewModel: PQViewModel
) {

    val dataOrException = viewModel.data.value
    val navController = rememberNavController()
    val currentBackStack by navController.currentBackStackEntryAsState()
    val currentDestination = currentBackStack?.destination
    val currentScreen =
        HomeTabRowScreens.find { it.route == currentDestination?.route } ?: GalleryView

    Scaffold(
        topBar = {
            HomeScreenTabRow(
                allScreens = HomeTabRowScreens,
                onTabSelected = { newScreen ->
                    navController
                        .navigateSingleTopTo(newScreen.route)
                },
                currentScreen = currentScreen,
            )
        }
    ) { innerPadding ->
        NavHost(
            navController = navController,
            startDestination = GalleryView.route,
            modifier = Modifier.padding(innerPadding)
        ) {
            composable(route = GalleryView.route) {
                // GalleryTabScreen()
                GalleryCollection(dataOrException = dataOrException)
            }
            composable(route = VirtualTourView.route) {
                VirtualTourScreen()
            }
        }

    }
}

fun NavHostController.navigateSingleTopTo(route: String) =
    this.navigate(route) {
        popUpTo(
            this@navigateSingleTopTo.graph.findStartDestination().id
        ) {
            saveState = true
        }
        launchSingleTop = true
        restoreState = true
    }

Finally calling the Home class in my main screen(MainActivity)

NavHost(
            ..
        ) {
            composable(NAV_HOME) {
                Home()
            }
            composable(..) { ...}
            
        }

The issue is when I run the app the tabs in the Home navBar doesn't show at all talk of loading the images from the firestore collection. Also, is there another way to instantiate a viewModel without having to create a class that extends ComponentActiviy?

If there's another way to achieve this kindly share.

0 Answers
Related