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
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)
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.
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)
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}")
}
})
}
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
}
}