0

New to Kotlin and to OOP in general I have a TextView in my MainActivity which is linked to a var

var int = 0
findViewById<TextView>(R.id.textView).setText("$var")

The thing is I want to modify this var inside and adapter.

class Adapter(
    var myContext: Context,
    var resource: Int,
    var values: ArrayList<List>
) : ArrayAdapter<List>(myContext, resource, values) {

    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
        val element = values[position]
        val view = LayoutInflater.from(myContext).inflate(resource, parent, false)
        
        findViewByID<Button>(R.id.button).setOnClickListener{
             int ++
             View(myContext).findViewByID<TextView>(R.id.textView).setText("$var")
             //here I get an error
        }
    }
}

I don’t know if this is clear enough. I saw I can use an interface Class but the thing is I don’t want to pass a data but to update one that already exists.

Elsouk
  • 3
  • 2

1 Answers1

0

You are using ArrayAdapter. If you are going to use adapters, you should use RecyvlerView.Adapter. Since you are learning, this is a perfect point to scratch that and learn Compose instead, with that out of the way.

The interface solution is the correct solution:

interface MyAdapterCallback {
    fun onButtonClicked(clickCount: Int)
}

Then implement it in your activity

class MyActivity : ..., MyAdapterCallback {

    override fun onButtonClicked(clickCount: Int) {
        findViewById<TextView>(R.id.textView).setText("$clickCount")
    }

}

You have to pass it to your adapter, this should be the same for array adapter or recycler, because is passing it in the constructor and then using it.

class Adapter(
    ...,
    private val callback: MyAdapterCallback
) {
  

   ...setOnClickListener{
             int ++ //this will work as long as int here is a valid thing
             callback.onButtonClicked(int)
        }

}

You might see this pattern with the delegate naming instead, I'm using callback just to try to make it clearer.

Another dirty solution would be to, pass the view to the adapter.

class Adapter(
    ...,
    private val myView: TextView
) {
  

   ...setOnClickListener{
             int ++ //this will work as long as int here is a valid thing
             myView.text = "$int"
        }

}

That is a very bad solution because it breaks the separations of concern principle, you should use it only for debugging.

Finally, the problem that you are currently having is this:

View(myContext).findViewByID<TextView>(R.id.textView).setText("$var")

That is instantiating a new View and inside that View you are trying to find the R.id.textView, that view is completely new so it has nothing inside. Your R.id.textView is in the activity layout, a completely different view. So the method findViewByID returns null. However you declare that the method should found non null TextView that why it crashes, if you change it to TextView? then it will be handle as nullable and it won't crash, but is pointless because it doesn't exist. The method findViewByID doesn't search in every place, just inside the View you are accessing.

cutiko
  • 9,887
  • 3
  • 45
  • 59
  • Thanks for this detailed answer. Ok then I need to improve my oriented object skills. And by the way as you are advising I will switch to jetpack compose. I was actually wondering if that could be better for me or not. – Elsouk Jan 05 '23 at 09:23
  • @Elsouk please remember how SO works and mark my answer as correct if it is so – cutiko Jan 05 '23 at 11:02
  • I actually don’t how SO works. Is it ok now? – Elsouk Jan 05 '23 at 12:54
  • I appreciate you have marked the answer as correct; it is ok for me; the important is that you mark the answer as correct when it is indeed correct. That is how SO works, questions get answers, and question owners can mark answers as correct. – cutiko Jan 05 '23 at 17:09