RecyclerView: No adapter attached; skipping layout 46545 - kotlin

Does anybody know a WORKING solution? None of the other threads helped.
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
binding = ActivityMainBinding.inflate(layoutInflater)
binding.mainRecyclerView.layoutManager = LinearLayoutManager(this)
binding.mainRecyclerView.setHasFixedSize(true)
adapter = MainRecyclerAdapter(this, null)
binding.mainRecyclerView.adapter = MainRecyclerAdapter(this, null)
}

Do this :
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.mainRecyclerView.layoutManager = LinearLayoutManager(this)
binding.mainRecyclerView.setHasFixedSize(true)
adapter = MainRecyclerAdapter(this, null)
binding.mainRecyclerView.adapter = MainRecyclerAdapter(this, null)
when you use View Binding , you must pass the root view to setContentView()

Related

How to create a RecyclerView with horizontal scroll? - Kotlin

set this
android:orientation="horizontal"
app:reverseLayout="true"
in the layout doesn't work.
When setting your layout manager set it like so in your Activity.kt file:
mRecyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, true);
class HorizontalRecyclerViewActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_horizontal_recycler_view)
val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
recyclerView.adapter = YourAdapter()
}
}
The layoutManager property of the RecyclerView to a LinearLayoutManager with its orientation set to HORIZONTAL. The third argument of the LinearLayoutManager constructor sets the reverse layout, in this case false, meaning that the items will be laid out from left to right.
Then, you set the adapter property of the RecyclerView to an instance of YourAdapter, which is a custom adapter that provides data to the RecyclerView.

E/RecyclerView: No adapter attached; skipping layout ERROR (FragmentHome)

I have a problem with RecyclerView in a Fragment. In FeedActivity. I want to show the RecyclerView in my first tab but I keep getting the following error:
I am getting this error when displaying recylerview inside home fragment.
recyclerview is not displayed on the screen at all.
I tried to run it under Oncreate() but it didn't work, how can I do it?
Can you help me how can I solve this?enter image description here
**class HomeFragment : Fragment() {**
private lateinit var auth : FirebaseAuth
private lateinit var db : FirebaseFirestore
private lateinit var binding: FragmentHomeBinding
val postArrayList : ArrayList<Post> = ArrayList()
var adapter : FeedRecyclerAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_home, container, false)
return view
** binding.recyclerView.layoutManager = LinearLayoutManager(activity)
adapter = FeedRecyclerAdapter(postArrayList)
binding.recyclerView.adapter = adapter**
auth = FirebaseAuth.getInstance()
db = FirebaseFirestore.getInstance()
getDataFromFirestore()
}
fun getDataFromFirestore() {
db.collection("Posts").orderBy("date",
Query.Direction.DESCENDING).addSnapshotListener { snapshot, exception ->
if (exception != null) {
Toast.makeText(context,exception.localizedMessage, Toast.LENGTH_LONG).show()
} else {
if (snapshot != null) {
if (!snapshot.isEmpty) {
postArrayList.clear()
val documents = snapshot.documents
for (document in documents) {
val comment = document.get("comment") as String
val useremail = document.get("userEmail") as String
val downloadUrl = document.get("downloadUrl") as String
//val timestamp = document.get("date") as Timestamp
//val date = timestamp.toDate()
val post = Post(useremail,comment, downloadUrl)
postArrayList.add(post)
}
adapter!!.notifyDataSetChanged()
}
}
}
}
}
}
**class FeedRecyclerAdapter(private val postList : ArrayList<Post>) : RecyclerView.Adapter<FeedRecyclerAdapter.PostHolder>() {**
class PostHolder(val binding: RecyclerRowBinding) : RecyclerView.ViewHolder(binding.root) {
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PostHolder {
val binding = RecyclerRowBinding.inflate(LayoutInflater.from(parent.context),parent,false)
return PostHolder(binding)
}
override fun getItemCount(): Int {
return postList.size
}
override fun onBindViewHolder(holder: PostHolder, position: Int) {
holder.binding.recyclerEmailText.text = postList.get(position).email
holder.binding.recyclerCommentText.text = postList.get(position).comment
Picasso.get().load(postList[position].downloadUrl).into(holder.binding.recyclerImageView)
}
}
Here you should return the view at the ed of the function, after you set your recyclerView:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_home, container, false)
return view //here this should be at the end
** binding.recyclerView.layoutManager = LinearLayoutManager(activity)
adapter = FeedRecyclerAdapter(postArrayList)
binding.recyclerView.adapter = adapter**
auth = FirebaseAuth.getInstance()
db = FirebaseFirestore.getInstance()
getDataFromFirestore()
}
Must be like this:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_home, container, false)
** binding.recyclerView.layoutManager = LinearLayoutManager(activity)
adapter = FeedRecyclerAdapter(postArrayList)
binding.recyclerView.adapter = adapter**
auth = FirebaseAuth.getInstance()
db = FirebaseFirestore.getInstance()
getDataFromFirestore()
return view //should be here
}
The solution is like this :
To solve the problem, I took the val view to the end, and then I encountered a new error, which I understood while solving it.
binding = FragmentHomeBinding.inflate(layoutInflater)
val view = binding.root
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
binding = FragmentHomeBinding.inflate(layoutInflater)
val view = binding.root
binding.recyclerView.layoutManager = LinearLayoutManager(activity)
adapter = FeedRecyclerAdapter(postArrayList)
binding.recyclerView.adapter = adapter
auth = FirebaseAuth.getInstance()
db = FirebaseFirestore.getInstance()
getDataFromFirestore()
return view

Boolean condition in kotlin was not executing

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_create_event)
activity = this#CreateEventActivity
var clicable = true
val set_data : ArrayList<Category_Spinner_model> = ArrayList<Category_Spinner_model>()
if(clicable) dropdown_lay.setOnClickListener{
category_recycler.layoutManager = LinearLayoutManager(this)
set_data.add(Category_Spinner_model(R.drawable.ic_facebook,"Entertainment",R.drawable.ic_dropdown_arrow))
set_data.add(Category_Spinner_model(R.drawable.ic__entertainment,"Entertainment",R.drawable.ic_dropdown_arrow))
set_data.add(Category_Spinner_model(R.drawable.ic__entertainment,"Entertainment",R.drawable.ic_dropdown_arrow))
val adapter = Category_recycler_view(set_data)
category_recycler.adapter = adapter
clicable = false
Log.e("clicable->","$clicable")
}
else if(!clicable) dropdown_lay.setOnClickListener{
set_data.clear()
val adapter = Category_recycler_view(set_data)
category_recycler.adapter = adapter
clicable = true
}
}
I have a recycler view and set data to that recycler view via adapter i need to show the recycler view when clicked and remove the recycler on other click
Your condition is out of place.
if(clicable) dropdown_lay.setOnClickListener{
...
}
Put it inside the onClickListener like this instead.
dropdown_lay.setOnClickListener{
if (clicable) {
category_recycler.layoutManager = LinearLayoutManager(this)
...
...
clicable = false
} else {
set_data.clear()
...
...
clicable = true
}
}

Kotlin retrofit recyclerview intent to new activity

so, i have a little problem here. in my Main Activity (CovidActivity) i want to show only "key" on my Adapter and then in my Second Activity (DetailCovidActivity) i want to show "kasus","sembuh","meninggal",and "dirawat". how to do that?
this is my CovidActivity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityCovidBinding.inflate(layoutInflater)
setContentView(binding.root)
adapterCovid = CovidAdapter(
listener = object: CovidAdapter.EventListener{
override fun onClick(itemList: CovidProvinceResponse.ListData) {
startActivity(
Intent(this#CovidActivity, DetailCovidActivity::class.java)
.putExtra("key",itemList.key)
.putExtra("kasus",itemList.jumlahKasus)
.putExtra("sembuh",itemList.jumlahSembuh)
.putExtra("meninggal",itemList.jumlahMeninggal)
.putExtra("dirawat",itemList.jumlahDirawat)
)
}
},listCovid = emptyList()
)
binding.rvShowCovid.adapter = adapterCovid
bindViewModel()
viewModel.getCovidProvince()
}
this is the onBindViewHolder in my Adapter
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val itemList = listCovid[position]
holder.binding.tvDaerah.text = itemList.key
holder.binding.tvJumlahKasus.text = itemList.jumlahKasus.toString()
holder.binding.tvJumlahSembuh.text = itemList.jumlahSembuh.toString()
holder.binding.tvJumlahMeninggal.text = itemList.jumlahMeninggal.toString()
holder.binding.tvJumlahDirawat.text = itemList.jumlahDirawat.toString()
holder.itemView.setOnClickListener {
listener.onClick(itemList)
}
}
and then this is the Second Activity (DetailCovidActivity)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDetailCovidBinding.inflate(layoutInflater)
setContentView(binding.root)
val province = intent.getStringExtra("key")
val kasus = intent.getIntExtra("kasus",0)
val sembuh = intent.getIntExtra("sembuh",0)
val meninggal = intent.getIntExtra("meninggal",0)
val dirawat = intent.getIntExtra("dirawat",0)
binding.tvDetailDaerah.text = province
binding.tvDetailKasus.text = kasus.toString()
binding.tvDetailSembuh.text = sembuh.toString()
binding.tvDetailMeninggal.text = meninggal.toString()
binding.tvDetailDirawat.text = dirawat.toString()
}

Context in fragment for recyclerview - Kotlin

I should be able to resolve this as their are so many similar posts on Stack but my brain is just not getting it...
I'm fairly new to android (from flutter) and I want a recyclerview in a fragment... moreover the recycler view doesn't use XML but a custom view class created by some JSON/GSON. None of the online tutorials really cover this and the Stack articles deal with one or another part but not all combined.
I think I have setup my custom views and adapter ok, but no matter what I try I am getting errors from my fragment, mostly related to the context and null parameters.
Here is my fragment class:
class MySquibsFragment : Fragment() {
//var squibGrid: RecyclerView = RecyclerView(requireContext())
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val v: View = inflater.inflate(R.layout.fragment_my_squibs, container, false)
//squibGrid = v.findViewById<RecyclerView>(R.id.squibgrid)
return v
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val squibList: ArrayList<SquibModel> = ArrayList()
try {
val jsonString = getJSONFromAssets()!!
val squibs = Gson().fromJson(jsonString, Squibs::class.java)
//squibGrid.layoutManager = LinearLayoutManager(activity)
//val itemAdapter = MySquibsAdapter(requireActivity(), squibs.squibs)
//squibGrid.adapter = itemAdapter
} catch (e: JSONException) {
e.printStackTrace()
}
}
The parts that are commented out are the lines that are throwing errors. I've tried moving all of onCreate into onActivityCreated and I've tried using lateinit to get the context, I just can't get my head around it.
Writing val squibGrid = view.findViewById<RecyclerView>(R.id.squibgrid) at the top means that you're trying to find the view when your fragment object is initialized. At that time, the fragment's view is not inflated, so you'll get an exception.
The fragment's view is inflated in onCreateView()
val v: View = inflater.inflate(R.layout.fragment_my_squibs, container, false)
return v
Try moving everything to onViewCreated(). According to the docs for fragment's lifecycle onViewCreated() is called after onCreateView(), i.e after the view is inflated.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val squibGrid = view.findViewById<RecyclerView>(R.id.squibgrid)
try {
val jsonString = getJSONFromAssets()!!
val squibs = Gson().fromJson(jsonString, Squibs::class.java)
squibGrid.layoutManager = LinearLayoutManager(activity)
val itemAdapter = MySquibsAdapter(requireActivity(), squibs.squibs)
squibGrid.adapter = itemAdapter
} catch (e: JSONException) {
e.printStackTrace()
}
}
Context in fragments will be available after onAttachContext method is called, also your views won't be created before onCreateView, it will crash if you try to access squibGrid in onCreate, You can safely bet on onViewCreated method where context and views are already available to consume
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val squibList: ArrayList<SquibModel> = ArrayList()
try {
val jsonString = getJSONFromAssets()!!
val squibs = Gson().fromJson(jsonString, Squibs::class.java)
//squibGrid.layoutManager = LinearLayoutManager(activity)
//val itemAdapter = MySquibsAdapter(requireActivity(), squibs.squibs)
//squibGrid.adapter = itemAdapter
} catch (e: JSONException) {
e.printStackTrace()
}
}