Search code examples
androidfirebasegoogle-cloud-firestorefirebaseuiandroid-paging

Android query data using FirestorePagingAdapter from multiple documents


I have a collection of users and a collection of recipesenter image description here

And I'm using FirestorePagingAdapter to display and paginate data, I want to show recipes (title and image..) with user details(name and photo)

I could display recipes, but I couldn't get user details in the same query(there is no join in Firestore)

This is my code :

fun setUpHomeAdapter(){
    var mQuery: Query = firestore.collection("recipes")
    // Init Paging Configuration
    val config = PagedList.Config.Builder()
        .setInitialLoadSizeHint(5)
        .setEnablePlaceholders(true)
        .setPrefetchDistance(5)
        .setPageSize(5)
        .build()
    // Init Adapter Configuration
    val options = FirestorePagingOptions.Builder<Recipe>()
        .setLifecycleOwner(this)
        .setQuery(mQuery, config, Recipe::class.java)
        .build()

    mAdapter = RecipesHomePagingAdapter(options, this)

    homeRecyclerView.adapter = mAdapter
}

My Adapter :

class RecipesHomePagingAdapter(
options: FirestorePagingOptions<Recipe>,
val listener: RecipesHomeViewHolder.OnItemRecipeClickListener) : FirestorePagingAdapter<Recipe, 
                                                                 RecipesHomeViewHolder>(options) {


override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecipesHomeViewHolder {
    val view =
            LayoutInflater.from(parent.context).inflate(
                R.layout.fragment_recipe_home_item,
                parent,
                false
            )

    return RecipesHomeViewHolder(view, listener)
}


override fun onBindViewHolder(holder: RecipesHomeViewHolder, position: Int, recipe: Recipe) {
    holder.bind(recipe)
}

My ViewHolder :

 class RecipesHomeViewHolder(itemView: View, private val listener: OnItemRecipeClickListener) :
RecyclerView.ViewHolder(itemView), View.OnClickListener {

private var imageRecipe: ImageView = itemView.findViewById(R.id.image_recipe)
private var title: TextView = itemView.findViewById(R.id.title)
private var nameuser: TextView = itemView.findViewById(R.id.user_name)
private var calories: TextView = itemView.findViewById(R.id.calories_textview)
private var layout_image_recipe: RelativeLayout =
    itemView.findViewById(R.id.layout_image_recipe)
private  var id_recipe: String?=null

fun bind(recipe: Recipe) {
    Glide
        .with(imageRecipe.context)
        .load(recipe.imageUrl)
       // .diskCacheStrategy(DiskCacheStrategy.ALL)
        .placeholder(R.drawable.ic_recipe_placeholder)
        .error(R.drawable.ic_recipe_placeholder)
        .into(imageRecipe)

    calories.text = recipe.calories.toString() + " Calories"
    title.text = recipe.title
    //nameuser.text = recipe.user_uid

}

init {
    layout_image_recipe.setOnClickListener(this)
}

override fun onClick(v: View?) {
    val position = adapterPosition
    if (position != RecyclerView.NO_POSITION) {
        listener.onViewClick(v!!, position, id_recipe)

    }
}

interface OnItemRecipeClickListener {
    fun onViewClick(v: View, position: Int, id_recipe:String?)

}

}

Thanks for any help to resolve the problem!


Solution

  • Unfortunately, you cannot pass two queries to FirestorePagingOptions, only one is allowed. The simplest thing I can think of is to add user details as properties in your Recipe object. If you cannot do that, there is another option in which you can create two separate queries and pass the result to an adapter, but in that case, you won't be able to use FirestorePagingAdapter anymore. However, pagination can still be archived by combining query cursors with the limit() method. For that, I recommend you check my answer from the following post:

    And take a look at this video for a better understanding.

    If you want to want to use the modern Paging 3 library, please check the following article: