Unresolved reference WearableRecyclerView.Adapter error in Kotlin - android

I'm trying to create an android wear app with a list of items. To enable circular scrolling, I'm using WearableRecyclerView by coding in kotlin. But facing this error Unresolved reference: Adapter The same code in java doesn't throw this error! I've also referred the inner and outer classes concepts in kotlin. Adapter class is an abstract class of RecyclerView which in turn is extended by WearableRecyclerView. Any guidance will be of much use, Thankyou!!
Here is my code
class CustomRecyclerAdapter(context: Context,dataSet: Array<String>): WearableRecyclerView.Adapter<CustomRecyclerAdapter.viewHolder>() {
var mDataSet: Array<String>
var mcontext: Context
init {
mDataSet = dataSet
mcontext=context
}
inner class viewHolder(view: View) : WearableRecyclerView(mcontext) {
val mTextView: TextView
init {
mTextView = view.findViewById(R.id.textView)
}
override fun toString(): String {
return mTextView.text as String
}
}
fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): viewHolder {
val view = LayoutInflater.from(viewGroup.context)
.inflate(R.layout.recycler_row_item, viewGroup, false)
return viewHolder(view)
}
fun onBindViewHolder(viewHolder: viewHolder, position: Int) {
// Replaces content of view with correct element from data set
viewHolder.mTextView.text = mDataSet[position]
}
// Return the size of your dataset (invoked by the layout manager)
fun getItemCount(): Int {
return mDataSet.size
}
}

Rather than using a (apparently non existent) WearableRecyclerView.Adapter consider using the non-wearable adapter: RecyclerView.Adapter

Your class inner class viewHolder(view: View) : WearableRecyclerView(mcontext) must extends WearableRecyclerView.ViewHolder instead of WearableRecyclerView like :
inner class viewHolder(view: View) : WearableRecyclerView.ViewHolder(view)

Related

Why does my code not enter this adapter class?

I'm new to Kotlin and Android studio.
I'm trying to get a recycle view to work properly but I'm running into a problem when trying to use an adapter class.
I tried taking a look with breakpoints. but it seems to trigger on the very first line where the class gets defined. ( so class OrganisationsAdapter...etc ) and after that it skips the whole class, it doesnt even enter it.
I also don't get any exceptions.
Adapter Class
class OrganisationsAdapter(
private val myDataset: Array<String>
) : RecyclerView.Adapter<OrganisationsAdapter.MyViewHolder>() {
class MyViewHolder(
val textView: TextView
) : RecyclerView.ViewHolder(textView) {
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
var cell = LayoutInflater.from(parent.context).inflate(R.layout.example_item, parent, false)
val textView = cell.findViewById<TextView>(R.id.organisation_name)
return MyViewHolder(textView)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.textView.text = myDataset[position]
}
override fun getItemCount() = myDataset.size
}
**The line I use to call the class **
recyclerViewOrganisationFragment.adapter = OrganisationsAdapter(Array(getTopics().size) { i -> getTopics()[i].name })
You need to pass the inflated layout to ViewHolder instead of TextView
ex:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
var cell = LayoutInflater.from(parent.context).inflate(R.layout.example_item, parent, false)
return MyViewHolder(cell)
}
class MyViewHolder(
val itemView: View
) : RecyclerView.ViewHolder(itemView) {
//TODO get textview here itemView.findViewByID
}
Update the viewholder accordingly with textview etc.,
Thank you Lakhwinder.
"You need to pass on ArrayList on the constructor of the adapter, you are passing a size"

Overriding 'top level function'

I'm trying to create a BaseRecyclerViewAdapter<T>:RecyclerView.Adapter<T> class to provide a default/common functionality for classes using generics. Because of the difference in view models' the onBindViewHolder and onCreateViewHolder methods throw NotImplementedError on the base class. Now when I want to implement the methods in the classes which inherit BaseRecyclerViewAdapter<T>, I encounter the following error:
Modifier 'override' is not applicable to 'top level function'
How can I safely override those without encountering this error?
Base.kt:
package com.example
abstract class BaseAdapter<T, THolder: RecyclerView.ViewHolder> (
private val mValues: List<T>,
private val mListener: OnFragmentInteractionListener<T>?
) : RecyclerView.Adapter<THolder>() {
private val mOnClickListener: View.OnClickListener
init {
mOnClickListener = View.OnClickListener { v ->
val item = v.tag as T
mListener?.onListFragmentInteraction(item)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): THolder {
throw NotImplementedError()
}
override fun onBindViewHolder(holder: THolder, position: Int) {
throw NotImplementedError()
}
override fun getItemCount(): Int = mValues.size
//And some other fancy methods
}
Other class.kt:
package com.example
class TheAdapter(
private val mValues: List<Item>,
private val mListener: OnFragmentInteractionListener<Item>?
) : BaseAdapter<Item, ViewHolder>(mValues, mListener)
//Error here
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
}
//Error here
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
}
inner class ViewHolder(val mView: View) : RecyclerView.ViewHolder(mView) {
//ViewHolder properties and methods
}
}
You've overloaded the class name ViewHolder. The ViewHolder in your class definition is RecyclerView.ViewHolder. The one in your function signature is your inner class. You need to specify your inner one in the class definition: BaseAdapter<String, TheAdapter.ViewHolder> to avoid the confusion. Or better yet, use a different class name for your inner class.

Constructor of inner class ViewHolder can be called only with receiver of containing class

I want to set a listener on RecyclerView items using RxJava2. The items are checkboxes. I want to listen to each item separately.
So I am getting an error Constructor of inner class ViewHolder can be called only with receiver of containing class in the
return TraceAdapter.ViewHolder(view)
class TraceAdapter(private var checkList: List<TraceViewModelRow> = listOf()) :
RecyclerView.Adapter<TraceAdapter.ViewHolder>() {
private val publishSubject = PublishSubject.create<Event>()
val events: Observable<Event> = publishSubject
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TraceAdapter.ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_trace_task, parent, false)
return TraceAdapter.ViewHolder(view)
}
override fun getItemCount(): Int = checkList.size
override fun onBindViewHolder(holder: TraceAdapter.ViewHolder, position: Int) {
holder.bindTraceList(checkList[position])
}
override fun onViewRecycled(holder: ViewHolder) {
super.onViewRecycled(holder)
}
inner class ViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView), LayoutContainer {
fun bindTraceList(trace: TraceViewModelRow) {
with(trace) {
checkbox_itemText.clicks()
.map { checkList[layoutPosition] }
.subscribe { publishSubject }
checkbox_itemText.text = description
checkbox_itemText.isChecked = isChecked
}
}
}
}
I think you just need to change this line:
return TraceAdapter.ViewHolder(view)
to this:
return ViewHolder(view)
As you've explicitly marked it as an inner class, it requires an instance of the outer class, which you get by default because you're constructing it from within the outer class. However only if you don't prefix it with the outer class type, as shown above.
The distinction between inner and nested classes is a bit different in Kotlin and Java (Java uses the term static for nested classes that don't have an instance of the outer class). It's explained in more detail here.

Can't access view in holder

I'm trying to create RecyclerView adapter and following this documentation.
private class Adapter(private val list: List<HashMap<String, Any>>, private val ctx: Context) : RecyclerView.Adapter<Adapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Adapter.ViewHolder {
var mTextView: TextView
return ViewHolder(ctx.UI {
relativeLayout {
mTextView = textView("1 + 1 = 2")
}
}.view)
}
override fun getItemCount() = list.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.mTextView.text = "1 + 1 = 3" // Should work?
}
class ViewHolder(view: View) : RecyclerView.ViewHolder(view)
}
How can I access mTextView in the onBindViewHolder?
If you're using kotlin extensions and have a text view with an id mTextView, then it should be:
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.itemView.mTextView.text = "1 + 1 = 3" // Should work?
}
You can also define variables in your ViewHolder and use them directly, this is the best way in terms of performance as it won't force unecessary calls to findviewbyid:
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val myTextView = itemView.mTextView
}
And later access it like:
holder.myTextView.text = "some text"
I was also facing Unresolved reference when trying to access views in onBindViewHolder.
override fun onBindViewHolder(holder: TodoViewHolder, position: Int) {
//Unresolved reference fooView
holder.itemView.fooView.text
}
In the end it turned out I was just missing the kotlinx import atop
import kotlinx.android.synthetic.main.myLayout.view.*
...And adding the extensions plugin in my app's build.gradle file.
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-android-extensions' //here
}
Adding the dependency and the import fixed it for me.
What you need to do here is to create a property for your TextView inside your ViewHolder. This isn't particularly easy with Anko, but here are some ways to do it.
1. Pass every View you want be able to reference from your ViewHolder as a separate constructor parameter.
For this solution, you have to modify your ViewHolder class like this, adding a property for the TextView:
class ViewHolder(view: View, val mTextView: TextView) : RecyclerView.ViewHolder(view)
You can initialize this property in this slightly convoluted way:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Adapter.ViewHolder {
lateinit var mTextView: TextView
val view = ctx.UI {
relativeLayout {
mTextView = textView("1 + 1 = 2")
}
}.view
return ViewHolder(view, mTextView)
}
While this doesn't look very nice, you're keeping the reference to your TextView from when you're initially creating it, so it's efficient.
2. Give your Anko created View instances IDs and look them up by their IDs later.
First, you have to create constants for your IDs - the ID can be any positive number, just make sure they're unique within the scope you're using them. One way is to place these inside a companion object, like so:
companion object {
private const val TEXT_VIEW_ID = 123 // Arbitrary positive number
}
Then, you need to give this ID to your TextView:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Adapter.ViewHolder {
return ViewHolder(ctx.UI {
relativeLayout {
textView("1 + 1 = 2") {
id = TEXT_VIEW_ID
}
}
}.view)
}
Finally, you can find your TextView again in your ViewHolder class with findViewById:
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val mTextView: TextView = view.findViewById(TEXT_VIEW_ID)
}
Of course this is going to be slower, because you're losing the TextView reference you already had when you're passing in the View to the ViewHolder, and then you're looking it up again.
Note that I stuck with mTextView for the answer so that it's easier to follow, but it's generally not recommended to use Hungarian notation or any other name prefixes in Kotlin.

Why can't I use the var mSelectedItem in inner class ViewHolder?

I define mSelectedItem as a public var in the class CustomAdapter, I think mSelectedItem=getAdapterPosition() will be Ok when I use mSelectedItem in inner class ViewHolder.
But it failed, and display "Unresolved reference: mSelectedItem" error, why?
And more, what is good way for getAdapterPosition() in Kotlin, there is hint which display "This inspection reports calls to java get and set methods that can be replaced with use of Kotlin synthetic properties", but it will cause errro when I use mSelectedItem=getAdapterPosition .
class CustomAdapter (val backupItemList: List<MSetting>) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
public var mSelectedItem = -1
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.item_recyclerview, parent, false)
return ViewHolder(v)
}
override fun onBindViewHolder(holder: CustomAdapter.ViewHolder, position: Int) {
holder.bindItems(backupItemList[position])
holder.itemView.radioButton.setChecked(position == mSelectedItem);
}
override fun getItemCount(): Int {
return backupItemList.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bindItems(aMSetting: MSetting) {
itemView.radioButton.tag=aMSetting._id
itemView.textViewUsername.text=aMSetting.createdDate.toString()
itemView.textViewAddress.text=aMSetting.description
mSelectedItem=getAdapterPosition() //It will cause error
}
}
}
If you don't want to make the ViewHolder an inner class (which you should not), you could create a class like AdapterSelection that has a field var selectedItem:Int inside it and replace your public var mSelectedItem = -1 with private var mSelectedItem = AdapterSelection(-1). Then pass the mSelectedItem to the bind method (bindItems(aMSetting: MSetting, adapterSelection:AdapterSelection) and inside the bind, set the position adapterSelection.selectedItem = getAdapterPosition().
You could have passed the adapter itself, but it is messy, that's why I suggest making another class.
ViewHolder is the Recycler rather than the operator.if you want to get the position,you put this mSelectedItem = position in onBindViewHolder.And this method named getAdapterPosition() always works on with notifyItemsetChanged().hope this will help you.

Categories

Resources