0

I am trying to display the posts from my Firebase into a recyclerView inside a Fragment. It works if I have the following code inside an "Activity" but if I want to have it inside a Fragment, the "Post Adapter" activity and the fragment file complains about the "context".

The XML files are built correctly because if I have the code inside an Activity it displays the posts as expected. So the problems comes from one of these to files.

Fragment:

package com.giveandshareauth.Fragments

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.Toast
import androidx.fragment.app.Fragment
import com.giveandshareauth.LoginActivity
import com.giveandshareauth.PostActivity
import com.giveandshareauth.PostAdapter
import com.giveandshareauth.R
import com.giveandshareauth.models.Post
import com.google.firebase.database.FirebaseDatabase
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.storage.StorageReference
import kotlinx.android.synthetic.main.fragment_account.*
import kotlinx.android.synthetic.main.fragment_home.*


import android.util.Log
import androidx.recyclerview.widget.LinearLayoutManager


import kotlinx.android.synthetic.main.fragment_home.*

private const val TAG = "PostActivity"

class HomeFragment : Fragment() {

    private lateinit var firestoreDB: FirebaseFirestore // lateinit because it will be initialised inside OnCreate method and it should never be known
    private lateinit var posts: MutableList<Post>
    lateinit var filepath: Uri
    private var imageUri: Uri? = null
    private var storagePostImages: StorageReference? = null
    private var database = FirebaseDatabase.getInstance().reference
    private lateinit var adapter: PostAdapter

    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View? = inflater.inflate(R.layout.fragment_home, container,false)

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        //layout file
        //data source
        posts = mutableListOf()
        //adapter
        adapter = PostAdapter(getActivity().context, posts)
        //bind the adapter and layout
        postsList.adapter = adapter
        postsList.layoutManager = LinearLayoutManager(getActivity().context)

        firestoreDB = FirebaseFirestore.getInstance()
        val postsRef = firestoreDB
                .collection("posts")
                .limit(10)                      //show last 10 posts
                .orderBy("post_time", com.google.firebase.firestore.Query.Direction.DESCENDING)
        postsRef.addSnapshotListener { snapshot, exception ->
            if (exception != null || snapshot == null) {
                Log.e(com.giveandshareauth.TAG, "There is an exception when querying posts", exception)
                return@addSnapshotListener
            }
            val postList = snapshot.toObjects(Post::class.java)
            posts.clear()
            posts.addAll(postList)
            adapter.notifyDataSetChanged()
            for (post in postList) {
                Log.i(com.giveandshareauth.TAG, "Post ${post}")
            }
        }



}

}

PostAdaper:

package com.giveandshareauth

import android.text.format.DateUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.giveandshareauth.Fragments.HomeFragment
import com.giveandshareauth.models.Post
import kotlinx.android.synthetic.main.item.view.*

class PostAdapter(val context: HomeFragment, val posts: List<Post>) :
    RecyclerView.Adapter<PostAdapter.ViewHolder>(){



    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(context).inflate(R.layout.item, parent,false)
        return ViewHolder(view)
    }


    override fun getItemCount() = posts.size

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(posts[position])
    }

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        fun bind(post: Post) {
            itemView.username.text=post.user?.username
            itemView.btnDescription.text=post.description
            Glide.with(context).load(post.imageUrl).into(itemView.products)
            itemView.time.text = DateUtils.getRelativeTimeSpanString(post.postTime)
        }

    }


}
  • use `requireActivity()!!`[notnull] or `activity?`[nullable] instead of `this` https://stackoverflow.com/questions/8215308/using-context-in-a-fragment – Ananiya Jemberu May 05 '21 at 19:43

1 Answers1

0

Hi my friend you can remove context from your adapter constructor and override the some methods like this

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val view = LayoutInflater.from(parent.context).inflate(R.layout.item, parent,false)
    return ViewHolder(view)
}

inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    fun bind(post: Post) {
        itemView.username.text=post.user?.username
        itemView.btnDescription.text=post.description
        Glide.with(itemview.context).load(post.imageUrl).into(itemView.products)
        itemView.time.text = DateUtils.getRelativeTimeSpanString(post.postTime)
    }
Mahdi Zareei
  • 1,299
  • 11
  • 18
  • It worked, thank you very much! I kept my context in the adapter constructor. And for the Fragment I set the context as "activity". But everything works as planned. Thank you! – babyoda May 06 '21 at 01:52