elliotching
elliotching

Reputation: 1092

Access a variable outside of an anonymously implemented interface in Kotlin (using Object)

I've confused my life in fixing this.
In short, I cannot access Context in outside of anonymous Kotlin object.

First, I got this plain basic recycler view adapter stuff.

class CashAdapter(private val cashList: List<Cash>, private val clickedAction: ClickedListener) : RecyclerView.Adapter<CashViewHolder>() {

    interface ClickedListener {
        fun onItemClick(cash: Cash)
    }

    // the rest of plain basic recycler view adapter stuff
}

Then, I got a plain basic Activity in using the adapter as following:

class MainActivity : AppCompatActivity() {
    internal val context: Context = this
    private val cashList: MutableList<Cash> = ArrayList()
    private lateinit var recyclerView: RecyclerView
    private lateinit var mAdapter: CashAdapter
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding =
            DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
        recyclerView = binding.rvCash
        mAdapter = CashAdapter(cashList, object: CashAdapter.ClickedListener{
            override fun onItemClick(cash: Cash) {
                val intent = Intent(context, NewActivity::class.java) // context <-- is NOT ACCESSIBLE because of the context is OUTSIDE of 'object'
                this.startActivityForResult(intent, NEW_ACTIVITY_REQUEST_CODE, null)
            }
        })
        val mLayoutManager: RecyclerView.LayoutManager = LinearLayoutManager(applicationContext)
        recyclerView.setLayoutManager(mLayoutManager)
        recyclerView.setItemAnimator(DefaultItemAnimator())
        recyclerView.setAdapter(mAdapter)
        prepareCashData()
    }
}

So I'm stuck at here. Anything outside of object is inaccessible and I'm pretty sure this is absolutely no problem with plain old JAVA

mAdapter = CashAdapter(cashList, new CashAdapter.ClickedListener(){
    void onItemClick(cash: Cash) {
        Intent intent = Intent(context, NewActivity.class)
        this.startActivityForResult(intent, NEW_ACTIVITY_REQUEST_CODE, null)
    }
})

to prove that I did tried something

class MainActivity : AppCompatActivity() {
    internal val context: Context = this
    private val cashList: MutableList<Cash> = ArrayList()
    private lateinit var recyclerView: RecyclerView
    private lateinit var mAdapter: CashAdapter
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding =
            DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
        recyclerView = binding.rvMovies
        mAdapter = CashAdapter(cashList, action)
        val mLayoutManager: RecyclerView.LayoutManager = LinearLayoutManager(applicationContext)
        recyclerView.setLayoutManager(mLayoutManager)
        recyclerView.setItemAnimator(DefaultItemAnimator())
        recyclerView.setAdapter(mAdapter)
        prepareMovieData()
    }

    private fun goToNextActivity() {
        val intent = Intent(context, NewActivity::class.java)
        this.startActivityForResult(intent, NEW_ACTIVITY_REQUEST_CODE, null)
    }

    object action: CashAdapter.ClickedListener{
        override fun onItemClick(cash: Cash) {
            goToNextActivity() // <-- CANNOT FIND THIS METHOD
        }
    }
}

I've confused my life at this point.

Ended up I implemented in top-level class as:

class MainActivity : AppCompatActivity(), CashAdapter.ClickedListener {
    override fun onCreate(savedInstanceState: Bundle?) {
        // ...
        mAdapter = CashAdapter(cashList, this)
        // ...
    }
    override fun onItemClick(cash: Cash) {
        val intent = Intent(context, NewActivity::class.java)
        this.startActivityForResult(intent, NEW_ACTIVITY_REQUEST_CODE, null)
    }
}

Yes, This works.

But what I want to know is about the case of anonymous implementation. What is the exact solution for that? Thanks for reading

Upvotes: 0

Views: 607

Answers (2)

a23sokolov
a23sokolov

Reputation: 603

If you change on this all will be Ok.

private val action = object: CashAdapter.ClickedListener{
    override fun onItemClick(cash: Cash) {
        goToNextActivity()
    }
}

object action: CashAdapter.ClickedListener it's like static CashAdapter.ClickedListener action. As a result when you call goToNextActivity() in static method, it doesn't have reference on Instance of MainActivity.

Upvotes: 1

Rub&#233;n Viguera
Rub&#233;n Viguera

Reputation: 3584

When you use this on an anonymous class in kotlin you refer to the actual class you are implementing, CashAdapter in this case:

this.startActivityForResult(intent, NEW_ACTIVITY_REQUEST_CODE, null)

Just use the following to tell kotlin that this clause refers to MainActivity and not your anonymous object of CashAdapter:

[email protected](intent, NEW_ACTIVITY_REQUEST_CODE, null)

Upvotes: 2

Related Questions