How to attach adapter to RecyclerView - java

I have been reading the different answers here on stackoverflow and tried to implement their solutions but I am still getting the error:
E/RecyclerView: No adapter attached; skipping layout
This error is logged in Log.cat .When I try to attach recyclerView Adapter in fragment .
This is the adapter which want to attached with the recyclerView
Adapter
class SubjectViewHolder(override val containerView: View):
RecyclerView.ViewHolder(containerView)
, LayoutContainer {
fun bind(subject: Subject, listener: CursorRecyclerViewAdapter.OnSubjectClickListener) {
subject_list_name.text = subject.name
subject_list_present.text = subject.present.toString()
subject_list_total.text = subject.totalClass.toString()
subject_list_delete.setOnClickListener {
Log.d(TAG,"delete button tapped. task name is ${subject.name}")
listener.onDeleteClick(subject)
}
}
}
private const val TAG="CursorViewAdapt"
class CursorRecyclerViewAdapter(private var cursor: Cursor?, private val listener: OnSubjectClickListener) :
RecyclerView.Adapter<SubjectViewHolder>(){
interface OnSubjectClickListener {
fun onDeleteClick(subject: Subject)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SubjectViewHolder {
Log.d(TAG,"onSubjectViewHolder: new view requested")
val view= LayoutInflater.from(parent.context).inflate(R.layout.subject_list,parent,false)
Log.d(TAG,"onCreateViewHolder: ends")
return SubjectViewHolder(view)
}
override fun getItemCount(): Int {
Log.d(TAG,"getItemCount: starts")
val cursor=cursor// to remove the smart cast problem
val itemcount= if(cursor==null || cursor.count==0){
1
}else{
cursor.count
}
Log.d(TAG,"returning $itemcount")
return itemcount
}
override fun onBindViewHolder(holder: SubjectViewHolder, position: Int) {
Log.d(TAG, "onBindViewHolder: starts")
val cursor = cursor //avoid problems with smart cast
if (cursor == null || cursor.count == 0) {
holder.subject_list_name.setText("Instruction_heading")
} else {
if (!cursor.moveToPosition(position)) {
throw IllegalStateException("Couldn't move cursor to position $position")
}
val task = Subject(
cursor.getString(cursor.getColumnIndex(SubjectContract.Columns.SUBJECT_NAME)),
cursor.getInt(cursor.getColumnIndex(SubjectContract.Columns.TOTAL_PRESENT)),
cursor.getInt(cursor.getColumnIndex(SubjectContract.Columns.TOTAL_CLASS))
)
task.id = cursor.getLong(cursor.getColumnIndex(SubjectContract.Columns.ID))
holder.bind(task, listener)
}
}
fun swapCursor(newCursor: Cursor?): Cursor?{
if (newCursor==cursor){
return null
}
val numItems=itemCount
val oldCursor=cursor
cursor=newCursor
if (newCursor!=null){
notifyDataSetChanged()
}else{
notifyItemRangeRemoved(0,numItems)
}
return oldCursor
}
}
MainActivityFragment
private const val TAG="MainActivityFragment"
class MainActivityFragment : Fragment(),
CursorRecyclerViewAdapter.OnSubjectClickListener {
interface OnUpdate{
fun onUpdate()
}
private val viewModel by lazy { ViewModelProvider(requireActivity()).get(AttendanceViewModel::class.java) }
private val mAdapter=CursorRecyclerViewAdapter(null,this )
override fun onCreate(savedInstanceState: Bundle?) {
Log.d(TAG,"onCreate: starts")
super.onCreate(savedInstanceState)
viewModel.cursor.observe(this, Observer { cursor-> mAdapter.swapCursor(cursor)?.close() })
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
Log.d(TAG,"onCreateView: called")
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_main_activity, container, false)
}
override fun onAttach(context: Context) {
Log.d(TAG,"onAttach: called")
super.onAttach(context)
if (context !is OnUpdate){
throw RuntimeException("${context.toString()} must implement OnTaskEdit")
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Log.d(TAG,"attaching Adapter")
sli.layoutManager= LinearLayoutManager(context)
sli.adapter=mAdapter
}
override fun onDeleteClick(subject: Subject) {
viewModel.deleteSubject(subject.id)
}
}

Related

The RecyclerView scrolls to downward when a new message is added

I have a chat app. I used RecyclerView and I set stackFromEnd true and reverseLayout false to LinearlayoutManager. when a new message is added at the bottom I mean at the end of the list the recyclerView starts auto scroll downward instead of upward. the adapter is notified by notifyItemInserted().
Expected Behaviour: When a new message is added to the list it should scroll to the bottom or upward. Any help is appreciated. Thanks,
Here is adapter:
class ChatMessagesListAdapter(
var chatMessages: ChatMessagesDataModel
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
companion object {
// we set the header as 0 so we can add more types to the ConversationItem enum
private const val ITEM_TYPE_HEADER = 0
}
override fun getItemViewType(position: Int): Int {
return when {
chatMessages.hasMoreItems -> chatMessages.messages[position].getItemType()
position == 0 -> ITEM_TYPE_HEADER
else -> chatMessages.messages[position - 1].getItemType()
}
}
// return +1 to draw the header if there are no items to load
override fun getItemCount() = chatMessages.messages.size + getContentIndex()
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return when (viewType) {
ITEM_TYPE_HEADER -> {
MessagesHeaderViewHolder(inflater.inflate(R.layout.item_chat_messages_header,
parent, false))
}
ChatItemDataModel.TYPE_ADDED_USER,
ChatItemDataModel.TYPE_VIDEO_NOTIFICATION -> {
MessagesInfoViewHolder(inflater.inflate(R.layout.item_chat_messages_info,
parent, false))
}
else -> {
MessagesMessageViewHolder(inflater.inflate(R.layout.item_chat_messages_message,
parent, false))
}
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
(holder as? MessagesHeaderViewHolder)?.bind()
(holder as? MessagesMessageViewHolder)?.bind(position, chatMessages.messages[getRealPosition(position)])
(holder as? MessagesInfoViewHolder)?.bind(chatMessages.messages[getRealPosition(position)])
}
private fun getContentIndex() = if (chatMessages.hasMoreItems) {
0
} else {
1
}
private fun getRealPosition(position: Int) = if (chatMessages.hasMoreItems) {
position
} else {
position - 1
}
private fun notifyChanges() {
if (chatMessages.numberOfItemsInserted == chatMessages.messages.size || isPreview ||
chatMessages.hadPendingMessages) {
notifyDataSetChanged()
} else {
// +1 because of the header
notifyItemRangeInserted(chatMessages.insertionIndex + getContentIndex(),
chatMessages.numberOfItemsInserted)
}
}
fun updateConversation(newChatMessages: ChatMessagesDataModel) {
chatMessages = newChatMessages
notifyChanges()
}
fun updateMessage(newMessage: ChatItemDataModel, isRemote: Boolean) {
if (newMessage.message.hashIdentifier.isNullOrBlank()) {
addNewMessage(newMessage)
return
}
val messageIndex = chatMessages.messages.indexOfFirst { it.message.hashIdentifier == newMessage.message.hashIdentifier }
if (messageIndex != -1) {
val localMessage = chatMessages.messages[messageIndex]
chatMessages.messages[messageIndex] = newMessage
if (failedMessages.contains(localMessage.message.sid)) {
if (isRemote) {
failedMessages.remove(localMessage.message.sid)
}
notifyItemChanged(messageIndex + getContentIndex())
}
}
else {
addNewMessage(newMessage)
}
}
private fun addNewMessage(newMessage: ChatItemDataModel) {
val oldCount = chatMessages.messages.size
chatMessages.messages.add(newMessage)
notifyItemInserted(oldCount + getContentIndex())
}
fun addLocalMessage(
sharedPrefsStorage: SharedPrefsStorage,
message: String, imageUri: Uri?, hashIdentifier: String
) {
val userMessage = UserMessage(messageBody = message, firstName = sharedPrefsStorage.firstName,
lastName = sharedPrefsStorage.lastName, isFromLoggedUser = true, imageUri = imageUri,
hashIdentifier = hashIdentifier, files = null, reactions = null)
val newMessage = ChatItemDataModel(userMessage, sharedPrefsStorage.profileImageUrl, sharedPrefsStorage.userId.toString())
val oldCount = chatMessages.messages.size
chatMessages.messages.add(newMessage)
notifyItemRangeInserted(oldCount + getContentIndex(), 1)
}
....
}
Here is Fragment:
class ChatRoomMessagesFragment : Fragment() {
#Inject
lateinit var sharedPrefsStorage: SharedPrefsStorage
private var adapter: ChatMessagesListAdapter? = null
......
override fun onMessagesReceived(chatMessages: ChatMessagesDataModel) {
if (adapter == null) {
adapter = ChatMessagesListAdapter(chatMessages)
adapter?.setHasStableIds(true)
binding.recyclerview.adapter = adapter
} else {
adapter?.updateConversation(chatMessages)
}
}
override fun onUserMessageRetrieved(newMessage: ChatItemDataModel, isRemote: Boolean) {
adapter?.updateMessage(newMessage, isRemote)
}
private fun setupUI() {
binding.apply {
recyclerview.apply {
layoutManager = LinearLayoutManager(requireContext()).apply {
reverseLayout = false
stackFromEnd = true
addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
showScrollToBottomButtonIfNeeded(findFirstCompletelyVisibleItemPosition())
}
})
}
addOnScrollListener(object : PaginationScrollListener(
layoutManager as LinearLayoutManager,
ScrollDirection.BOTTOM
) {
override fun loadMoreItems() {
presenter.loadMoreMessages()
}
override fun isLastPage() = !presenter.hasMoreItems()
override fun isLoading() = presenter.isLoadingInProgress()
})
// prevent the list from scrolling when the keyboard opens
addOnLayoutChangeListener { _, _, _, _, bottom, _, _, _, oldBottom ->
if (bottom < oldBottom) {
scrollChatToBottom()
}
}
}
....
adapter?.addLocalMessage(sharedPrefsStorage, message, imageUri, hashIdentifier)
presenter.sendMessage("", message, imageUri, hashIdentifier)
}
private fun scrollChatToBottom() {
binding.apply {
recyclerview.post {
recyclerview.smoothScrollToPosition(recyclerview.adapter?.itemCount ?: 0)
}
}
}
}
Let's suppose your adapter is populated by objects called messages and you have a source of data called messageList (could be a Collection, etc) that is passed to your adapter. You could do something like this:
int position = messageList.size() > 0 ? (messageList.size()-1) : 0;
mRecyclerView.smoothScrollToPosition(position);
Just ensure your adapter is not null and actually gets data from messageList since this is in your Activity/Fragment class and not in the adapter class.
You can scrolldown progrmatically using code below
recyclerView.scrollToPosition(chatList.size() - 1);
You can also try another solution if above one doesn't works
setStackFromEnd(true) or setReverseLayout(true)
yourAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
super.onItemRangeInserted(positionStart, itemCount)
this#EventDetails.binding.rvData.scrollToPosition(positionStart)
}
override fun onItemRangeChanged(positionStart: Int, itemCount: Int) {
super.onItemRangeChanged(positionStart, itemCount)
this#EventDetails.binding.rvData.scrollToPosition(positionStart)
}
})
one of these method will work i think 1st one, try
and
try to avoid notifyDataSetChange() or intemChange() call by your self use DiffUtils or ListAdapter(Extension of recycler view)

How to save data from RecyclerView (ArrayList) with Kotlin?

I have a RecyclerView created in Kotlin and would like to save the data from the RecyclerView (the ArrayList) for example with GSON Libary. I've already searched a lot but can't find a working solution. Here's my current code: (without saving function)
MainActivity.kt:
class MainActivity : AppCompatActivity(), ExampleAdapter.OnItemClickListener {
private val exampleList = generateDummyList(500)
private val adapter = ExampleAdapter(exampleList, this)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recycler_view.adapter = adapter
recycler_view.layoutManager = LinearLayoutManager(this)
recycler_view.setHasFixedSize(true)
}
fun insertItem(view: View) {
val index = Random.nextInt(8)
val newItem = ExampleItem(
R.drawable.ic_android,
"New item at position $index",
"Line 2"
)
exampleList.add(index, newItem)
adapter.notifyItemInserted(index)
}
fun removeItem(view: View) {
val index = Random.nextInt(8)
exampleList.removeAt(index)
adapter.notifyItemRemoved(index)
}
override fun onItemClick(position: Int) {
Toast.makeText(this, "Item $position clicked", Toast.LENGTH_SHORT).show()
val clickedItem = exampleList[position]
clickedItem.text1 = "Clicked"
adapter.notifyItemChanged(position)
}
private fun generateDummyList(size: Int): ArrayList<ExampleItem> {
val list = ArrayList<ExampleItem>()
for (i in 0 until size) {
val drawable = when (i % 3) {
0 -> R.drawable.ic_android
1 -> R.drawable.ic_audio
else -> R.drawable.ic_sun
}
val item = ExampleItem(drawable, "Item $i", "Line 2")
list += item
}
return list
}
}
ExampleItem.kt:
data class ExampleItem(val imageResource: Int, var text1: String, var text2: String)
ExampleAdapter.kt:
class ExampleAdapter(
private val exampleList: List<ExampleItem>,
private val listener: OnItemClickListener) :
RecyclerView.Adapter<ExampleAdapter.ExampleViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ExampleViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.example_item,
parent, false)
return ExampleViewHolder(itemView)
}
override fun onBindViewHolder(holder: ExampleViewHolder, position: Int) {
val currentItem = exampleList[position]
holder.imageView.setImageResource(currentItem.imageResource)
holder.textView1.text = currentItem.text1
holder.textView2.text = currentItem.text2
}
override fun getItemCount() = exampleList.size
inner class ExampleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
View.OnClickListener {
val imageView: ImageView = itemView.image_view
val textView1: TextView = itemView.text_view_1
val textView2: TextView = itemView.text_view_2
init {
itemView.setOnClickListener(this)
}
override fun onClick(v: View?) {
val position = adapterPosition
if (position != RecyclerView.NO_POSITION) {
listener.onItemClick(position)
}
}
}
interface OnItemClickListener {
fun onItemClick(position: Int)
}
}
First you need to convert you Data in to json by using json object in onBindViewHolder using
String json = {"phonetype":"N95","cat":"WP"};
try {
JSONObject obj = new JSONObject(json);
Log.d("My App", obj.toString());
} catch (Throwable t) {
Log.e("My App", "Could not parse malformed JSON: \"" + json + "\"");
}
And if you want to save then you can use shared preferences.

notifyDataSetChanged does not work in adapter in kotlin

There is a delete button on my recylerview item when I click it I m showing a alert dialog when I click yes button I want to refresh my recylerview but I could'not. I call directly notifyDataSetChanged in adapter at the end of the my code but it does not work.
MyAlertDialog(In my adapter)
mAlertDialog.setPositiveButton("Yes") { dialog, id ->
val databaseHandler: DBHelper = DBHelper(holder.itemView.context)
val removedMed = Medicine(id = medicine.id,name = medicine.name,amount = medicine.amount,description = medicine.description)
databaseHandler.deleteMedicine(removedMed)
dialog.dismiss()
notifyDataSetChanged()
}
Mainactivity
class MainActivity : AppCompatActivity() {
private var adapter: MedicineAdapter? = null
private var medicineList : ArrayList<Medicine> = arrayListOf()
private var recyclerView: RecyclerView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
getDataFromDb()
}
fun getDataFromDb(){
val context = this
val db = DBHelper(context)
recyclerView = findViewById<View>(R.id.recyclerView) as RecyclerView
adapter = MedicineAdapter(this, db.readData())
val layoutManager = LinearLayoutManager(applicationContext)
recyclerView!!.layoutManager = layoutManager
recyclerView!!.itemAnimator = DefaultItemAnimator()
// set the adapter
recyclerView!!.adapter = adapter
adapter!!.notifyDataSetChanged()
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) {
R.id.addBtn -> {
val intent = Intent(this,AddNewMedicine::class.java)
startActivity(intent)
true
}
else -> super.onOptionsItemSelected(item)
}
override fun onResume() {
super.onResume()
getDataFromDb()
}
}
MedicineAdapter
class MedicineAdapter(
private val mainActivity: MainActivity,
val medicineList: ArrayList<Medicine>)
: RecyclerView.Adapter<MedicineAdapter.ListItemHolder>(){
override fun onCreateViewHolder(
parent: ViewGroup, viewType: Int): ListItemHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.medicine_items, parent, false)
return ListItemHolder(itemView)
}
inner class ListItemHolder(view: View) :
RecyclerView.ViewHolder(view),
View.OnClickListener {
internal var name = view.findViewById<TextView>(R.id.name)
internal var amount = view.findViewById<TextView>(R.id.amount)
internal var description = view.findViewById<TextView>(R.id.description)
internal var deleteButton = view.findViewById<ImageButton>(R.id.deleteBtn)
internal var editButton = view.findViewById<ImageButton>(R.id.editBtn)
init {
view.isClickable = true
view.setOnClickListener(this)
deleteButton.setOnClickListener(this)
editButton.setOnClickListener(this)
}
override fun onClick(view: View) {
//val intentToCarPager = Intent(view!!.context, CarPagerActivity::class.java)
//view.context.startActivity(intentToCarPager)
}
}
override fun onBindViewHolder(holder: ListItemHolder, position: Int) {
val medicine = medicineList!![position]
holder.name.text = medicine.name
holder.amount.text = medicine.amount
holder.description.text = medicine.description
holder.deleteButton.setOnClickListener {
val mAlertDialog = AlertDialog.Builder(holder.itemView.context)
mAlertDialog.setTitle("Are you sure you want to this record!") //set alertdialog title
mAlertDialog.setPositiveButton("Yes") { dialog, id ->
val databaseHandler: DBHelper = DBHelper(holder.itemView.context)
val removedMed = Medicine(id = medicine.id,name = medicine.name,amount = medicine.amount,description = medicine.description)
databaseHandler.deleteMedicine(removedMed)
notifyDataSetChanged()
dialog.dismiss()
medicineList.removeAt(position)
notifyItemRemoved(position)
}
mAlertDialog.setNegativeButton("No") { dialog, id ->
}
mAlertDialog.show()
}
holder.editButton.setOnClickListener {
val dialog = UpdateMedicine(medicine)
val manager = (holder.itemView.context as MainActivity).supportFragmentManager
dialog.show(manager,"")
}
}
override fun getItemCount(): Int {
if (medicineList != null) {
return medicineList.size
}
return -1
}
}
I solved my problem by removing the object from the array
notifyDataSetChanged()
dialog.dismiss()
medicineList.removeAt(position)
notifyItemRemoved(position)

Java/Kotlin. No adapter attached; skipping layout. I dont know why i have this error

I Have NetworkRecycler class.I just want to show data to my textviews from server. I use retrofit library. In log i have error message: No adapter attached; skipping layout. Sorry for me English guys. This is my MainActivity class:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
val linearLayoutManager = LinearLayoutManager(this)
linearLayoutManager.orientation = LinearLayoutManager.VERTICAL
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("https://developers.themoviedb.org/")
.build()
val json = retrofit.create(JsonPlaceHolder::class.java)
val call = json.getNetworkId(3)
call.enqueue(object: Callback<List<Network>> {
override fun onResponse(call: Call<List<Network>>, response: Response<List<Network>>) {
val network = response.body()
val networkRecycler = NetworkRecycler(network!!)
recyclerView.apply {
layoutManager = linearLayoutManager
adapter = networkRecycler
}
}
override fun onFailure(call: Call<List<Network>>, t: Throwable) {
Log.e("MainActivity", "${t.message}")
}
})
}
And this is my NetworkRecycler class:
class NetworkRecycler(private val list: List<Network>): RecyclerView.Adapter<NetworkRecycler.ViewHolder(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.recycler_list, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val network = list[position]
holder.headquarters.text = network.headquarters
holder.homepage.text = network.homepage
holder.id.text = network.id.toString()
holder.name.text = network.name
holder.originCountry.text = network.origin_country
}
override fun getItemCount(): Int = list.size
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val headquarters : TextView = itemView.findViewById(R.id.headquarters)
val homepage : TextView = itemView.findViewById(R.id.homepage)
val id : TextView = itemView.findViewById(R.id.textId)
val name : TextView = itemView.findViewById(R.id.name)
val originCountry : TextView = itemView.findViewById(R.id.origin_country)
}
}
Finally my Network class:
data class Network(
val headquarters: String,
val homepage: String,
val id: Int,
val name: String,
val origin_country: String
)
You need to set your recyclerView with adapter first, then change the adapter when get the response. This code below may be work.
//define adapter with empty list
var networkRecycler = NetworkRecycler(ArrayList<Network>())
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
val linearLayoutManager = LinearLayoutManager(this)
linearLayoutManager.orientation = LinearLayoutManager.VERTICAL
//set your adapter here
recyclerView.apply {
layoutManager = linearLayoutManager
adapter = networkRecycler
}
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("https://developers.themoviedb.org/")
.build()
val json = retrofit.create(JsonPlaceHolder::class.java)
val call = json.getNetworkId(3)
call.enqueue(object: Callback<List<Network>> {
override fun onResponse(call: Call<List<Network>>, response: Response<List<Network>>) {
val network = response.body()
networkRecycler = NetworkRecycler(network!!)
//refresh recycler view
adapter.notifyDataSetChanged();
}
override fun onFailure(call: Call<List<Network>>, t: Throwable) {
Log.e("MainActivity", "${t.message}")
}
})
}

Show list from adapter in Object of Array form

I need to show a list from adapter. I've got the data with calling api, but it can't showed in the interface.
this is data model Table :
data class Table(val id : String, val nama: String, val tersedia: Boolean)
this is data model Tables that contain ArrayList of Table :
data class Tables (val daftarMeja : ArrayList<Table>)
this is mu adapter :
class MejaAdapter (private val tableList: ArrayList<Table>, private val clickListener: (Table) -> Unit) : RecyclerView.Adapter<RecyclerView.ViewHolder>(){
private lateinit var tables: Tables
override fun getItemCount(): Int {
return tableList.size
}
fun updateData(dataBaru: ArrayList<Table>) {
tableList.clear()
tableList.addAll(dataBaru)
Log.i("tableListAdapter","balbalbla" + tableList.toString())
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val cellForRow = layoutInflater.inflate(R.layout.item_meja,parent,false)
return PartViewHolder(cellForRow)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
(holder as PartViewHolder).bind(tableList[position], clickListener)
}
class PartViewHolder (itemView: View): RecyclerView.ViewHolder(itemView){
fun bind(table: Table, clicklistener: (Table) -> Unit){
itemView.tv_table_name.text = table.nama
if(table.tersedia){
itemView.container_table.setBackgroundResource(R.color.colorTableAvailable)
itemView.tv_table_name.setTextColor(Color.BLACK)
}
else {
itemView.container_table.setBackgroundResource(R.drawable.gradient)
itemView.tv_table_name.setTextColor(Color.WHITE)
}
itemView.setOnClickListener {clicklistener(table)}
}
}
}
and this fun the activity :
private lateinit var tableList: ArrayList<Tables>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_daftar_meja)
tableList = ArrayList()
/*init RecyclerView*/
recyclerView_meja.layoutManager = GridLayoutManager(this, numberOfColumns(), GridLayoutManager.VERTICAL, false)
recyclerView_meja.hasFixedSize()
/*Set Adapter*/
dataAdapter = MejaAdapter(tableItem) { tableItemClicked() }
recyclerView_meja.adapter = dataAdapter
//Show list table
val idCafe = user.cafeId
getTableList(idCafe)
}
private fun getTableList(idCafe:String){
val apiService : Service = Client.getClient()!!.create(Service::class.java)
apiService.getTable(idCafe).enqueue(object : Callback<Tables>{
override fun onResponse(call: Call<Tables>?, response: Response<Tables>?) {
Log.i("IdMeja", "id : " + response?.body())
if (response != null && response.isSuccessful) {
val listTable = response.body()
if (listTable == null) {
Toast.makeText(this#MainActivity, "Tidak ada meja", Toast.LENGTH_SHORT).show()
}
else{
tables = listTable
// update list table
Log.i("adapter", "$dataAdapter")
dataAdapter.updateData(tableList)
Toast.makeText(this#MainActivity, "hahaha$tables", Toast.LENGTH_SHORT).show()
}
}
else{
Log.i("idCafe", " $idCafe")
Toast.makeText(this#MainActivity, "Gagal dapat meja", Toast.LENGTH_SHORT).show()
}
}
override fun onFailure(call: Call<Tables>?, t: Throwable?) {
Log.i("fail",t.toString() )
Toast.makeText(this#MainActivity, "Gagal", Toast.LENGTH_SHORT).show()
}
})
}
I think the problem is in the adapter, but i don't know how to fix it.
Please help me to fix it.
We think this is a naming issue your use this line of code to name your View Holder
class MejaAdapter (private val tableList: ArrayList<Table>, private val clickListener: (Table) -> Unit) : RecyclerView.Adapter<RecyclerView.ViewHolder>(){
Where you call it ViewHolder
Then you start using PartViewHolder
So change the code to use a consistent name PartViewHolder looks good to us
Here is our Adapter look at the naming convention used
class ViewAdapter(private val parents:List<ModelParent>):RecyclerView.Adapter<ViewAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.the_view,parent,false)
return ViewHolder(view)
}
override fun getItemCount(): Int {
return parents.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val parent = parents[position]
holder.textView.text = parent.dept
holder.recyclerView.apply {
layoutManager = LinearLayoutManager(holder.recyclerView.context, LinearLayout.VERTICAL, false)
adapter = ViewChildAdapter(parent.children)
}
}
inner class ViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView){
val recyclerView : RecyclerView = itemView.rv_child
val textView: TextView = itemView.textView
}
}

Categories