Search code examples
androidkotlinandroid-context

Use right context


Need to paste context in my constructor in SwipeToDeleteCallback, which is located in the fragment:

private val swipeHandler = object : SwipeToDeleteCallback() {

    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
        presenter.removeListItem(viewHolder.adapterPosition)
    }
}

Tried to insert requireContext() but catch KotlinNullPointerException.

Maybe I can somehow use the context here viewHolder.context?

Here is some code SwipeToDeleteCallback:

abstract class SwipeToDeleteCallback(context: Context) :
    ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {

    private val deleteIcon = context.getDrawableCompat(R.drawable.ic_log_out)

Also i called my fragment from MainActivity:

override fun onPostResume() {
    super.onPostResume()
    replaceFragment(TargetsFragment())
}

override fun showListOfTarget() {
    replaceFragment(TargetsFragment())
}

Here is full code of my fragment:

class TargetsFragment : Fragment(), ListItemClickListener, SelectTargetViewContract, BaseDataSetContract {

    private var recyclerView: RecyclerView? = null
    private val presenter = TargetsPresenter(this)
    private var adapter = TargetsAdapter(clickListener = this)

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

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        presenter.setInitialData()
        setupViews()
        updateListData()
    }

    override fun onListItemClick(itemIndex: Int, itemCode: String) {
        presenter.onListItemClick((adapter.getItem(itemIndex) as Target).guid)
    }

    override fun showTarget(guid: String) {
        activity?.addFragment(TargetEditFragment.newInstance(guid))
    }

    override fun dataSetChanged() {
        updateListData()
        adapter.notifyDataSetChanged()
    }

    override fun updateViewContent() {
        adapter.data = presenter.targetList
        recyclerView?.adapter = adapter
        recyclerView?.setVisible(presenter.shouldShowContent())
        emptyView?.setVisible(presenter.shouldShowEmptyView())
    }

    private fun updateListData() {
        if (presenter.firebaseUser == null) {
            Log.d("some", "loadLogInView")
        } else {
            presenter.getTargetsFromDb()
        }
    }

    private val swipeHandler = object : SwipeToDeleteCallback() {

        override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
            presenter.removeListItem(viewHolder.adapterPosition)
        }
    }

    private fun setupViews() {
        recyclerView = view?.findViewById(R.id.recyclerView)
        recyclerView?.layoutManager = LinearLayoutManager(activity)
        ItemTouchHelper(swipeHandler).attachToRecyclerView(recyclerView)
    }
}

Solution

  • You can use

    yourViewHolder.itemView.context
    

    to get the context of yourViewHolder


    After clarification from OP:


    Initially I thought you only wanted to get context from your ViewHolder, but here's an addition to my answer:

    Try moving your code which requires context to onAttach, which you will have to override, from the documentation : https://developer.android.com/guide/components/fragments.html

    Caution: If you need a Context object within your Fragment, you can call getContext(). However, be careful to call getContext() only when the fragment is attached to an activity. When the fragment isn't attached yet, or was detached during the end of its lifecycle, getContext() returns null.

    The method you're looking for looks like this :

    override fun onAttach(context: Context) {
        super.onAttach(context)
    }
    

    You will probably be safe to move all your code which requires context inside this method and assign it as you need to