when I use this code, my recycler view app crashed because I got an null object reference exception bt at the moment I did not know how to fix it. I tried to softcode the strings in my view text but it does not work. When I hardcoded it, it works :(
The issue is in the line of
mContext.getString(R.string.strClick)
Here is my code:
package de.reuter.myapplication
import android.content.Context
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import de.reuter.timetable.RecycleAdapter
import kotlinx.android.synthetic.main.activity_content_backend.*
class BackendContentActivity : AppCompatActivity()
{
val mContext: Context = this
private val exampleList = generateDummyList(5, this)
private val adapter = RecycleAdapter(exampleList, mContext)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_content_backend)
recycler_view.adapter = adapter
recycler_view.layoutManager = LinearLayoutManager(this)
recycler_view.setHasFixedSize(true)
}
private fun generateDummyList(size: Int, mContext: Context): ArrayList<AdapterItems> {
val list = ArrayList<AdapterItems>()
var drawable: Int
var txt0: String
var txt1: String
var txt2: String = mContext.getString(R.string.strClick)
for (i in 0 until size) {
when (i % 5) {
0 -> {
drawable = R.drawable.bg_circle_blue
txt0 = "M"
txt1 = "Monday"
}
1 -> {
drawable = R.drawable.bg_circle_green
txt0 = "T"
txt1 = "Tuesday"
}
2 -> {
drawable = R.drawable.bg_circle_red
txt0 = "W"
txt1 = "Wednesay"
}
3 -> {
drawable = R.drawable.bg_circle_yellow
txt0 = "T"
txt1 = "Thursday"
}
4 -> {
drawable = R.drawable.bg_circle_purple
txt0 = "F"
txt1 = "Friday"
}
else -> {
drawable = R.drawable.bg_circle_purple
txt0 = "W"
txt1 = "Wrong"
}
}
var item = AdapterItems(drawable, txt0, txt1, txt2)
list += item
}
return list
}
}
My Recycler Adapter:
package de.reuter.timetable
import android.content.Context
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.snackbar.Snackbar
import de.reuter.myapplication.AdapterItems
import de.reuter.myapplication.MondayActivity
import de.reuter.myapplication.R
import kotlinx.android.synthetic.main.card_layout.view.*
class RecycleAdapter(private val exampleList: List<AdapterItems>, context: Context) :
RecyclerView.Adapter<RecycleAdapter.ExampleViewHolder>() {
var mContext = context
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ExampleViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(
R.layout.card_layout,
parent, false
)
return ExampleViewHolder(itemView)
}
override fun onBindViewHolder(holder: ExampleViewHolder, position: Int) {
val currentItem = exampleList[position]
holder.imageView.setImageResource(currentItem.imageResource)
holder.textView0.text = currentItem.text1
holder.textView1.text = currentItem.text2
holder.textView2.text = currentItem.text3
}
override fun getItemCount() = exampleList.size
inner class ExampleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var imageView: ImageView = itemView.image_view
var textView0: TextView = itemView.txtShortLetterM
var textView1: TextView = itemView.txtViewMonday
var textView2: TextView = itemView.txtClickLink
init {
imageView = itemView.findViewById(R.id.image_view)
textView0 = itemView.findViewById(R.id.txtShortLetterM)
textView1 = itemView.findViewById(R.id.txtViewMonday)
textView2 = itemView.findViewById(R.id.txtClickLink)
itemView.setOnClickListener { v: View ->
var position: Int = getAdapterPosition()
var text: String
when (position) {
0 -> {
var intent = Intent(mContext, MondayActivity::class.java)
mContext.startActivity(intent)
}
else -> {
text = "Click detected on item $position"
Snackbar.make(
v, text,
Snackbar.LENGTH_LONG
).setAction("Action", null).show()
}
}
}
}
}
}
Thank you very much for helping
Try to move generateDummyList(5, this) call to onCreate method of BackendContentActivity class:
class BackendContentActivity : AppCompatActivity() {
private lateinit var exampleList: ArrayList<AdapterItems>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_content_backend)
exampleList = generateDummyList(5, this)
// ...
}
// ...
}
Related
I am implementing a RecyclerView, holding itemViews of both VIEW_HEADER and VIEW_ITEM. Each header view item appears above a triplet of viewItem. When i am implementing both type of Views, i am only getting the first header in the run time of the recyclerview. When i disable the header View, i can get the results of the itemviews in sequential order.
Here is the declaration of the code for the recyclerview adapter:
package com.example.cvdriskestimator.CustomClasses
import android.graphics.drawable.Drawable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.cvdriskestimator.MainActivity
import com.example.cvdriskestimator.R
class leaderBoardRecyclerAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
val VIEW_ITEM = 0
val VIEW_HEADER = 1
private lateinit var prActivity: MainActivity
var nameDataSet = ArrayList<String>()
var participantAvatars = ArrayList<Drawable>()
private var currentPartId = 1
fun setActivity(mainActivity: MainActivity)
{
prActivity = mainActivity
}
override fun getItemViewType(position: Int): Int {
var view_type = (position % 4)
if (view_type == 0)
return VIEW_HEADER
else
return VIEW_ITEM
return VIEW_ITEM
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
when(viewType)
{
1 ->
{
val view : View = LayoutInflater.from(prActivity.applicationContext).inflate(R.layout.leaderboard_header_item_layout, parent , false)
return leaderHeaderViewHolder(view)
}
0 ->
{
val view : View = LayoutInflater.from(prActivity.applicationContext).inflate(R.layout.leaderboard_item_layout , parent , false)
return leaderBoardViewHolder(view)
}
}
val view = View(prActivity.applicationContext)
return leaderBoardViewHolder(view)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when(getItemViewType(position))
{
0 ->
{
//populate data for the viewHolder
var leaderBoardViewHolder = holder as leaderBoardViewHolder
leaderBoardViewHolder.part_name.text = nameDataSet[currentPartId - 1]
leaderBoardViewHolder.part_order_id.text = (currentPartId).toString()
leaderBoardViewHolder.part_avatar.setImageDrawable(participantAvatars[currentPartId-1])
currentPartId ++
leaderBoardViewHolder.part_score.text = leaderBoardViewHolder.calculateScore(currentPartId).toString()
}
1 ->
{
var leaderHeaderViewHolder = holder as leaderHeaderViewHolder
leaderHeaderViewHolder.leader_header_txtV.text = leaderHeaderViewHolder.setGroupLetter(currentPartId-1)
}
}
}
override fun getItemCount(): Int {
return nameDataSet.size
}
}
open class leaderBoardViewHolder : RecyclerView.ViewHolder
{
var part_order_id : TextView
var part_name : TextView
var part_avatar : ImageView
var part_rel_layout : RelativeLayout
var part_score : TextView
constructor(itemView: View) : super(itemView) {
part_rel_layout = itemView.findViewById(R.id.partRelLayout)
part_order_id = itemView.findViewById(R.id.partorderTxtV)
part_score = itemView.findViewById(R.id.partScoreTxtV)
part_name = itemView.findViewById(R.id.parttxtV)
part_avatar = itemView.findViewById(R.id.partAvatorImgV)
}
fun calculateScore(id : Int) : Int
{
val score = 10000 - (id * 500)
return score
}
}
class leaderHeaderViewHolder : RecyclerView.ViewHolder
{
var leader_header_txtV : TextView
constructor(itemView : View) : super(itemView) {
leader_header_txtV = itemView.findViewById(R.id.groupleadTxtV)
}
fun setGroupLetter(position : Int) : String
{
var result = (position / 3)
var letter = "A"
when(result)
{
0 ->
{
letter = "GROUP A"
}
1 ->
{
letter = "GROUP B"
}
2 ->
{
letter = "GROUP C"
}
3 ->
{
letter = "GROUP D"
}
}
return letter
}
}
And on the fragment, the declaration of the RecyclerView:
private fun initLeaderRecyclerView(view : View)
{
leaderboardRecyclerView = view.findViewById(R.id.leaderBoardRecyclerView)
populateDataForRecyclerView()
leaderBoardRecyclerAdapter = leaderBoardRecyclerAdapter()
leaderBoardRecyclerAdapter.setActivity(mainActivity)
leaderBoardRecyclerAdapter.nameDataSet = participantNames
leaderBoardRecyclerAdapter.participantAvatars = participantAvatars
leaderboardRecyclerView.apply {
adapter = leaderBoardRecyclerAdapter
}
var linearLayoutManager = LinearLayoutManager(mainActivity.applicationContext)
linearLayoutManager.orientation = LinearLayoutManager.VERTICAL
leaderboardRecyclerView.layoutManager = linearLayoutManager
}
Any ideas of why might this be occuring?
Thank you in advance,
Lampros
There was a problem with the recyclerview list being added only initially and not being added after the second.
MainActivity.kt
package com.malkinfo.editingrecyclerview
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.malkinfo.editingrecyclerview.added_data.Companion.start_time_hou
import com.malkinfo.editingrecyclerview.added_data.Companion.start_time_min
import com.malkinfo.editingrecyclerview.model.UserData
import com.malkinfo.editingrecyclerview.view.UserAdapter
class MainActivity : AppCompatActivity() {
private lateinit var addsBtn:FloatingActionButton
private lateinit var recv:RecyclerView
private lateinit var userList:ArrayList<UserData>
private lateinit var userAdapter:UserAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
userList = ArrayList()
addsBtn = findViewById(R.id.addingBtn)
recv = findViewById(R.id.mRecycler)
userAdapter = UserAdapter(this,userList)
recv.layoutManager = LinearLayoutManager(this)
recv.adapter = userAdapter
addsBtn.setOnClickListener {
startActivity(Intent(this#MainActivity,next_activity::class.java))
}
if(intent.hasExtra("name")){
addInfo2()
}
}
private fun addInfo2(): ArrayList<UserData> {
var names = start_time_hou
var number = start_time_min
userList.add(UserData("Name: ${names}","Mobile No. : $number"))
userAdapter.notifyDataSetChanged()
Toast.makeText(this,"${userList}",Toast.LENGTH_LONG).show()
return userList
}
}
UserAdapter.kt
package com.malkinfo.editingrecyclerview.view
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.recyclerview.widget.RecyclerView
import com.malkinfo.editingrecyclerview.R
import com.malkinfo.editingrecyclerview.model.UserData
class UserAdapter(val c:Context,val userList:ArrayList<UserData>):RecyclerView.Adapter<UserAdapter.UserViewHolder>()
{
inner class UserViewHolder(val v:View):RecyclerView.ViewHolder(v){
var name:TextView
var mbNum:TextView
var mMenus:ImageView
var mToggle:ToggleButton
init {
name = v.findViewById<TextView>(R.id.mTitle)
mbNum = v.findViewById<TextView>(R.id.mSubTitle)
mToggle=v.findViewById(R.id.toggleButton)
mMenus = v.findViewById(R.id.mMenus)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
val inflater = LayoutInflater.from(parent.context)
val v = inflater.inflate(R.layout.list_item,parent,false)
return UserViewHolder(v)
}
override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
val newList = userList[position]
holder.name.text = newList.userName
holder.mbNum.text = newList.userMb
}
override fun getItemCount(): Int {
return userList.size
}
}
next_activity.kt
package com.malkinfo.editingrecyclerview
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.malkinfo.editingrecyclerview.added_data.Companion.end_time_hou
import com.malkinfo.editingrecyclerview.added_data.Companion.end_time_min
import com.malkinfo.editingrecyclerview.added_data.Companion.start_time_hou
import com.malkinfo.editingrecyclerview.added_data.Companion.start_time_min
import kotlinx.android.synthetic.main.activity_next2.*
import kotlinx.android.synthetic.main.add_item.*
class next_activity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_next2)
button2.setOnClickListener {
finish()
}
button.setOnClickListener {
start_time_hou="1"
start_time_min="2"
end_time_hou=3
end_time_min=4
val intent_time= Intent(this#next_activity,MainActivity::class.java)
intent_time.putExtra("name","lir")
startActivity(intent_time)
}
button3.setOnClickListener {
start_time_hou="1123"
start_time_min="52"
val intent_time= Intent(this#next_activity,MainActivity::class.java)
intent_time.putExtra("name","lir")
startActivity(intent_time)
}
}
}
added_data.kt
package com.malkinfo.editingrecyclerview
class added_data {
companion object {
var start_time_hou = "0"
var start_time_min = "0"
var end_time_hou = 0
var end_time_min = 0
}
}
UserData.kt
package com.malkinfo.editingrecyclerview.model
data class UserData (
var userName:String,
var userMb:String
)
What I want is to move from MainACtivity to next_activity, and every time I press the button in next_activity, a new recycleview element is created. However, as I said earlier, there is no additional generation and only one element of data changes.
The issue here is, you are adding items to your userList in MainActivity but you are not passing them to the recyclerview. That is why userAdapter.notifyDataSetChanged() is not causing any effect.
Try this and let me know if there is still some issue :)
In MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var addsBtn:FloatingActionButton
private lateinit var recv:RecyclerView
private lateinit var userList:ArrayList<UserData>
private lateinit var userAdapter:UserAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
userList = ArrayList()
addsBtn = findViewById(R.id.addingBtn)
recv = findViewById(R.id.mRecycler)
userAdapter = UserAdapter(this)
userAdapter.setData(userList)
recv.layoutManager = LinearLayoutManager(this)
recv.adapter = userAdapter
addsBtn.setOnClickListener {
startActivity(Intent(this#MainActivity,next_activity::class.java))
}
if(intent.hasExtra("name")){
addInfo2()
}
}
private fun addInfo2(): ArrayList<UserData> {
var names = start_time_hou
var number = start_time_min
userList.add(UserData("Name: ${names}","Mobile No. : $number"))
userAdapter.setData(userList)
Toast.makeText(this,"${userList}",Toast.LENGTH_LONG).show()
return userList
}
}
UserAdapter
class UserAdapter(val c:Context):RecyclerView.Adapter<UserAdapter.UserViewHolder>()
{
private var _userList: ArrayList<UserData>? = null
inner class UserViewHolder(val v:View):RecyclerView.ViewHolder(v){
var name:TextView
var mbNum:TextView
var mMenus:ImageView
var mToggle:ToggleButton
init {
name = v.findViewById<TextView>(R.id.mTitle)
mbNum = v.findViewById<TextView>(R.id.mSubTitle)
mToggle=v.findViewById(R.id.toggleButton)
mMenus = v.findViewById(R.id.mMenus)
}
}
fun setData(userList: ArrayList<UserData>) {
_userList = userList
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
UserViewHolder {
val inflater = LayoutInflater.from(parent.context)
val v = inflater.inflate(R.layout.list_item,parent,false)
return UserViewHolder(v)
}
override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
val newList = _userList?.get(position)
holder.name.text = newList?.userName
holder.mbNum.text = newList?.userMb
}
override fun getItemCount(): Int {
if(_userList == null)
return 0
else
return _userList!!.size
}
}
I get error when I press button inside recycler view. My application is not crashing. I am trying to set a button in the recycler view and callingsetOnClickListener inside onBindViewHolder. Inside the holder.Button.setOnClickListener{}I change the button text to notified. But when I press a button the values of other button text in another list also changes. This is a listview of firestore documents. I have many documents that are uploaded into the recycler view. If I am getting the error how should I implement the button onclicklistener without this error.[![https://i.stack.imgur.com/S0Oxm.jpg][1]][1] [![enter image description here][2]][2]
/**This my activity for recycler view*/
package com.example.bloodbankcompany.recyclerview
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Adapter
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.bloodbankcompany.MyAdapter
import com.example.bloodbankcompany.R
import com.example.bloodbankcompany.User1
import com.example.bloodbankcompany.User2
import com.google.firebase.firestore.*
import java.lang.NullPointerException
class MainActivity2 : AppCompatActivity() {
private lateinit var recyclerView: RecyclerView
private lateinit var userArrayList: ArrayList<User2>
private lateinit var myAdapter: MyAdapter2
private val mFireStore = FirebaseFirestore.getInstance()
var db = FirebaseFirestore.getInstance()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
recyclerView= findViewById(R.id.recyclerview)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.setHasFixedSize(true)
userArrayList= arrayListOf()
myAdapter =MyAdapter2(userArrayList)
recyclerView.adapter = myAdapter
EventChangeListener()
}
private fun EventChangeListener() {
try {
mFireStore.collection("applicationForm").addSnapshotListener(object :
EventListener<QuerySnapshot> {
override fun onEvent(value: QuerySnapshot?, error: FirebaseFirestoreException?) {
if (error != null) {
Log.e("firestore error", error.message.toString())
}
try {
for (dc: DocumentChange in value?.documentChanges!!) {
if (dc.type == DocumentChange.Type.ADDED) {
userArrayList.add(dc.document.toObject(User2::class.java))
}
// Toast.makeText(applicationContext,userArrayList.toString(), Toast.LENGTH_SHORT).show()
}
} catch (e:NullPointerException){
}
myAdapter.notifyDataSetChanged()
}
})
} catch (e:NullPointerException){
}
}
}
/**
* This is my myAdapter activity for adapater*/
package com.example.bloodbankcompany.recyclerview
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.example.bloodbankcompany.R
import com.example.bloodbankcompany.RegisterActivity
import com.example.bloodbankcompany.User2
import com.google.firebase.firestore.FirebaseFirestore
import kotlinx.android.synthetic.main.list_item2.view.*
class MyAdapter2(private val userList: ArrayList<User2>): RecyclerView.Adapter<MyAdapter2.MyViewHolder>(){
var id: String = ""
private val mFireStore = FirebaseFirestore.getInstance()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyAdapter2.MyViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.list_item2,parent,false)
return MyViewHolder(itemView)
}
override fun onBindViewHolder(holder: MyAdapter2.MyViewHolder, position: Int) {
val user:User2 = userList[position]
holder.name.text= user.name
holder.phone.text= user.phone
holder.address.text =user.address
holder.bloodGroup.text= user.bloodgroup
holder.id.text = user.id
//Setting onclicklistener to my adapter and starting intent
holder.button.setOnClickListener {
// holder.io = "kkj"
// holder.id.text = " "
holder.button.setText("notified")
// val context=holder.button.context
// val intent = Intent( context, RegisterActivity::class.java)
// context.startActivity(intent)
}
}
override fun getItemCount(): Int {
return userList.size
}
public class MyViewHolder(itemView : View): RecyclerView.ViewHolder(itemView){
val name : TextView = itemView.findViewById(R.id.tvfirstname1)
val phone :TextView= itemView.findViewById(R.id.tvphone11)
val address : TextView= itemView.findViewById(R.id.tvaddress1)
val bloodGroup: TextView =itemView.findViewById(R.id.tvbloodg1)
val id: TextView = itemView.findViewById(R.id.tvid)
var io: String? = ""
var button: Button = itemView.findViewById(R.id.btn_notify)
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
init {
itemView.btn_notify.setOnClickListener {
}
}
}
}
} ```
[1]: https://i.stack.imgur.com/S0Oxm.jpg
[2]: https://i.stack.imgur.com/BqDMf.jpg
create interface for clickListener in your adapter and set it in constructor
interface OnItemClickListener {
fun onItemClick(position: Int)
}
and in ViewHolder set bind your button
fun bind(position: Int, listener: OnItemClickListener) {
button.setOnClickListener { v -> listener.onItemClick(position) }
}
and then set this code in onBindViewHolder
holder.bind( position , onItemClickListener)
finally when click on button you can action in Activity or Fragment
example :
adapter = Adapter(getContext(), models) { position -> }
Simple Code, Without using Interface
Actually what I found is you were doing it the correct way, but you were using two ViewHolder classes there which is the cause of issue. Try to use the below code once and try again. Hope it works.
class mAdapter(val context: Context, private val dataList: ArrayList<String>):
RecyclerView.Adapter<mAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): mAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.item_card_view, parent, false)
return mAdapter.ViewHolder(v)
}
override fun onBindViewHolder(holder: mAdapter.ViewHolder, position: Int) {
holder.txtView.setText(dataList.get(position))
//Your Button setOnClickLister
holder.btnName.setOnClickListener {
// action here
}
}
override fun getItemCount(): Int {
return dataList.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val txtView = itemView.findViewById(R.id.textView) as TextView
val btnName = itemView.findViewById(R.id.btnName) as Button
}
}
Peace
i have made simple recyclerview, with interface clickListener
consisting of 4 items showing toast on click.
It works fine if i single click per second,
but if i Rapidly click on different items ( 2 or 3 times in 1 seconds )
it still shows the toast each second,
not rapidly changing the toast
data class code:
package com.elsersy.rv5
data class Items (var textt:String) {
}
adapter code
package com.elsersy.rv5
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
class MyAdapter(private var stringList:ArrayList<Items>,private val listener:MyOnClickListener):
RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
inner class MyViewHolder(itemView:View):RecyclerView.ViewHolder(itemView) {
var text:TextView = itemView.findViewById(R.id.textView)
init {
itemView.setOnClickListener {
val position = absoluteAdapterPosition
if (position != RecyclerView.NO_POSITION)
{
listener.onItemClick(position)
}
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.row_item,parent,false)
return MyViewHolder(itemView)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val currentItem = stringList[position]
holder.text.text = currentItem.textt
}
override fun getItemCount(): Int {
return stringList.size
}
interface MyOnClickListener{
fun onItemClick(position: Int)
}
fun setData(newItemList:ArrayList<Items>){
val diffUtil = MyDiffUtil(stringList,newItemList)
val diffResults = DiffUtil.calculateDiff(diffUtil)
stringList = newItemList
diffResults.dispatchUpdatesTo(this)
}
}
ActivityMainCode
package com.elsersy.rv5
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import com.elsersy.rv5.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity(),MyAdapter.MyOnClickListener {
private lateinit var binding: ActivityMainBinding
private lateinit var stringList:ArrayList<Items>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
binding.recyclerView.layoutManager = LinearLayoutManager(this)
stringList = arrayListOf<Items>()
getStrings()
binding.recyclerView.adapter=MyAdapter(stringList,this)
}
private fun getStrings() {
for (a in 0..4){
var string_Array = resources.getStringArray(R.array.string_array)
stringList.add(Items(string_Array[a]))
}
}
override fun onItemClick(position: Int) {
Toast.makeText(this,"$position is clicked", Toast.LENGTH_SHORT).show()
}
}
If you want to cancel the previous toast before showing a new one, assign it as a member variable and cancel it before showing the new one:
private var toast : Toast? = null
..
override fun onItemClick(position: Int) {
toast?.cancel()
toast = Toast.makeText(this,"$position is clicked", Toast.LENGTH_SHORT)
toast?.show()
}
I have gone through some of the answers related to the topic but in code below I am the using any String method explicitly and hence I am not able to figure out the actual cause of error.
Code for MainScreenAdapter.kt file:
package adapters
import android.content.Context
import android.os.Bundle
import android.support.v4.app.FragmentActivity
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.RelativeLayout
import android.widget.TextView
import com.example.champion.echo_12.R
import fragments.SongPlayingFragment
import fragments.Songs
**class MainScreenAdapter(_songDetails: ArrayList<Songs>, _context: Context) :RecyclerView.Adapter<MainScreenAdapter.MyViewHolder>()** {
var songDetails: ArrayList<Songs>? = null
var mContext: Context? = null
init {
this.songDetails = _songDetails
this.mContext = _context
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val songObject = songDetails?.get(position)
holder.trackTitle?.text = songObject?.songTitle
holder.trackArtist?.text = songObject?.artist
holder.contentHolder?.setOnClickListener {
//Toast.makeText(mContext,songObject?.songTitle+" is Playing",Toast.LENGTH_SHORT).show()
val songPlayingFragment = SongPlayingFragment()
val args = Bundle()
args.putString("songArtist", songObject?.artist)
args.putString("songTitle", songObject?.songTitle)
args.putString("path", songObject?.songData)
//to int required here
args.putInt("songID",songObject?.songID?.toInt() as Int)
args.putInt("songPosition", position)
args.putParcelableArrayList("songData", songDetails)
songPlayingFragment.arguments = args
(mContext as FragmentActivity).supportFragmentManager
.beginTransaction()
.replace(R.id.details_fragment, songPlayingFragment)
.addToBackStack("SongPlayingFragment")
.commit()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
**val itemView = LayoutInflater.from(parent.context)
.inflate(R.layout.row_custom_mainscreen_adapter, parent, false)**
return MyViewHolder(itemView)
}
override fun getItemCount(): Int {
if (songDetails == null) {
return 0
}
else {
return (songDetails as ArrayList<Songs>).size
}
}
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
/*Declaring the widgets and the layout used*/
var trackTitle: TextView? = null
var trackArtist: TextView? = null
var contentHolder: RelativeLayout? = null
/*Constructor initialisation for the variables*/
init {
trackTitle = view.findViewById(R.id.trackTitle) as TextView
trackArtist = view.findViewById(R.id.trackArtist) as TextView
contentHolder = view.findViewById(R.id.contentRow) as RelativeLayout
}
}
}
Line 56 and Line 16(Bold marked **) are subjected to the error condition.
Call for MainScreenAdapter() Class.
package fragments
import adapters.MainScreenAdapter
import android.app.Activity
import android.content.Context
import android.os.Bundle
import android.provider.MediaStore
import android.support.v4.app.Fragment
import android.support.v7.widget.DefaultItemAnimator
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.RelativeLayout
import android.widget.TextView
import com.example.champion.echo_12.R
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
*
*/
class MainScreenFragment : Fragment() {
var getSongsList: ArrayList<Songs>? = null
var nowPlayingBottomBar: RelativeLayout? = null
var playPauseButton: ImageButton? = null
var songTitle: TextView? = null
var visibleLayout: RelativeLayout? = null
var noSongs: RelativeLayout? = null
var recyclerView: RecyclerView? = null
var myActivity: Activity? = null
var _mainScreenAdapter: MainScreenAdapter? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
val view = inflater!!.inflate(R.layout.fragment_main_screen, container, false)
visibleLayout = view?.findViewById(R.id.visibleLayout)
noSongs = view?.findViewById(R.id.noSongs)
nowPlayingBottomBar = view?.findViewById(R.id.hiddenBarMainScreen)
songTitle = view?.findViewById(R.id.songTitleMainScreen)
playPauseButton = view?.findViewById(R.id.playPauseButton)
recyclerView = view?.findViewById(R.id.contentMain)
return view
//return inflater.inflate(R.layout.fragment_main_screen, container, false)
}
override fun onAttach(context: Context?) {
super.onAttach(context)
myActivity=context as Activity
}
override fun onAttach(activity: Activity?) {
super.onAttach(activity)
myActivity=activity
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
getSongsList=getSongsFromPhone()
_mainScreenAdapter= MainScreenAdapter(getSongsList as ArrayList<Songs>,myActivity as Context)
val _mLayoutManager=LinearLayoutManager(myActivity)
recyclerView?.layoutManager=_mLayoutManager
recyclerView?.itemAnimator=DefaultItemAnimator()
recyclerView?.adapter=_mainScreenAdapter
}
fun getSongsFromPhone(): ArrayList<Songs>{
var arrayList = ArrayList<Songs>()
var contentResolver = myActivity?.contentResolver
var songUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
var songCursor = contentResolver?.query(songUri, null, null, null, null)
if (songCursor != null && songCursor.moveToFirst()) {
val songId = songCursor.getColumnIndex(MediaStore.Audio.Media._ID)
val songTitle = songCursor.getColumnIndex(MediaStore.Audio.Media.TITLE)
val songArtist = songCursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)
val songData = songCursor.getColumnIndex(MediaStore.Audio.Media.DATA)
val dateIndex = songCursor.getColumnIndex(MediaStore.Audio.Media.DATE_ADDED)
while (songCursor.moveToNext()) {
var currentId = songCursor.getLong(songId)
var currentTitle = songCursor.getString(songTitle)
var currentArtist = songCursor.getString(songArtist)
var currentData = songCursor.getString(songData)
var currentDate = songCursor.getLong(dateIndex)
arrayList.add(Songs(currentId, currentTitle, currentArtist, currentData, currentDate))
}
}
return arrayList
}
}
If any one could help me in pointing out the Reason for Null Reference then I would be very thankful.