0

Which context should I be using when I use a SharedPreference within a RecyclerView adapter? This is confusing as when during the default one, context in val mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) appears as an unresolved reference.

class MyRVAdapter(private val myString: ArrayList<String>): RecyclerView.Adapter<MyRVAdapter.MyViewHolder>() {
    private val typeA = 1
    private val typeB = 2

    override fun onCreateViewHolder(parent: ViewGroup, type: Int): MyViewHolder {
        return when (type) {
            typeA -> MyViewHolder(inflateHelper(R.layout.rv_type_a, parent))
            typeB -> MyViewHolder(inflateHelper(R.layout.rv_type_b, parent))
            else -> MyViewHolder(inflateHelper(R.layout.rv_type_a, parent))
        }
    }

    override fun onBindViewHolder(viewHolder: MyViewHolder, position: Int) {
        if (getItemViewType(position) == typeA) {
            // Check preference (what's the correct context?)
            val mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
            valueDestinationExpanded = mSharedPreferences.getBoolean("my_preference", true)
        }
        else if (getItemViewType(position) == typeB) {
        }
    }

    private fun inflateHelper(resId: Int, parent: ViewGroup): View {
        return LayoutInflater.from(parent.context).inflate(resId, parent, false)
    }

    override fun getItemViewType(position: Int): Int {
        return if (position == 0) typeA
        else typeB
    }
}

In fragment

myTV must not be null

class MyFragment : androidx.fragment.app.Fragment() {
    private lateinit var mRecyclerView: RecyclerView
    private var valueShowTextView: Boolean = false

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.my_rv, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        val v = view
        val myTV = my_tv

        mRecyclerView = v.mRecyclerViewSansToolbar

        mRecyclerView.layoutManager = LinearLayoutManager(activity)

        val mAdapter = MyRVAdapter(dataTVtext!!)

        val mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
        valueDestinationExpanded = mSharedPreferences.getBoolean("preference_DestinationExpand", true)

        if (valueShowTextView) {
            myTV.visibility = View.VISIBLE
        } else {
            myTV.visibility = View.GONE
        }

        mRecyclerView.adapter = mAdapter

        super.onActivityCreated(savedInstanceState)
    }
}
SD826E
  • 6,673
  • 7
  • 45
  • 92
  • The God Adapter pattern isn't so great. Consider defining an interface for your ViewHolder's item type and pass out the click event to your enclosing Fragment. – EpicPandaForce Feb 10 '20 at 22:43
  • @EpicPandaForce an example would help too so I'm on the right track. I'm trying to avoid large chunks of code if possible. – SD826E Feb 10 '20 at 22:52
  • See https://stackoverflow.com/questions/51867215/can-we-make-use-of-the-built-in-setonclicklistener-on-recyclerview-row-item-inst/51867792#51867792 – EpicPandaForce Feb 11 '20 at 07:59

2 Answers2

1

Any Context is fine. Your context reference is unresolved because you don't have a variable or property by that name, as you would from within a View or Activity. The most convenient way to get one in onBindViewHolder would be viewHolder.itemView.context (or viewHolder.itemView.getContext() from Java).

Ryan M
  • 11,512
  • 21
  • 38
  • 50
  • Is it possible to access Shared Preferences frmo a Fragment when the item I want to control is actually defined in a RecyclerView adapter? – SD826E Feb 10 '20 at 22:21
  • Yes. SharedPreferences with the same name (including the default) are shared across your entire app. – Ryan M Feb 10 '20 at 22:24
1

Shared Preferences is used for persisting data and isn't entirely suitable for use within a RecyclerView as its operations can slow down the application. See the developer documentation for more info on why it shouldn't necessarily be used in this way and where it is best applied.

In your case, it may be preferable to retrieve the data from SharedPreferences at some point prior to the initialization of your Adapter and pass it during initialization.

Assuming performance is not critical, you can continue doing it as before and simply retrieve a context from one of your views with viewHolder.itemView.context. You could also pass a context reference from your activity to the adapter.

B. Plüster
  • 464
  • 2
  • 10
  • Is it possible to access Shared Preferences frmo a Fragment when the item I want to control is actually defined in a RecyclerView adapter? – SD826E Feb 10 '20 at 22:18
  • SharedPreferences can be accessed from anywhere within your application, just make sure to use the same preferences, e.g. the default or same name. – B. Plüster Feb 10 '20 at 22:36
  • Not working for me as I'm trying to access a `TextView` from a different class but get this error: `myTV must not be null`. See my fragment code. – SD826E Feb 10 '20 at 22:42
  • This has nothing to do with your initial question and I cannot find the error without knowing more. Consider writing a new question to solve your next problem. Make sure to include all important code and what you have already tried or where you expect the problem may come from. – B. Plüster Feb 10 '20 at 23:05
  • I've posted a new question – SD826E Feb 10 '20 at 23:05