Android
Fragment
Activity
Method Invocation
Mobile Development

Call an activity method from a fragment

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Fragments often need the host activity to do something that only the activity controls, such as navigating, opening a dialog, or interacting with system UI. You can call an activity method from a fragment, but the clean solution depends on how tightly you want those two classes to be coupled.

Prefer an interface contract

The safest default is to define a small interface that represents what the fragment needs, then make the activity implement it. The fragment depends on a contract instead of a concrete activity class, which keeps the fragment reusable and easier to test.

kotlin
1interface HostActions {
2    fun openCheckout()
3}
4
5class CheckoutActivity : AppCompatActivity(), HostActions {
6    override fun onOpenSupportNavigateUp(): Boolean {
7        onBackPressedDispatcher.onBackPressed()
8        return true
9    }
10
11    override fun openCheckout() {
12        startActivity(Intent(this, PaymentActivity::class.java))
13    }
14}
15
16class CartFragment : Fragment(R.layout.fragment_cart) {
17    private var hostActions: HostActions? = null
18
19    override fun onAttach(context: Context) {
20        super.onAttach(context)
21        hostActions = context as? HostActions
22            ?: error("Host activity must implement HostActions")
23    }
24
25    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
26        val checkoutButton = view.findViewById<Button>(R.id.checkoutButton)
27        checkoutButton.setOnClickListener {
28            hostActions?.openCheckout()
29        }
30    }
31
32    override fun onDetach() {
33        hostActions = null
34        super.onDetach()
35    }
36}

There are two important details here. First, the reference is assigned in onAttach, which is the first point where the fragment is guaranteed to be connected to a context. Second, it is cleared in onDetach so the fragment does not keep a stale reference after it is removed.

This pattern is especially good when the fragment only needs one or two host actions and you want to avoid fragment code such as requireActivity() as MainActivity.

When a direct activity call is acceptable

If the fragment is permanently tied to a single activity and reusability is not a goal, a direct cast is shorter:

kotlin
1class ProfileFragment : Fragment(R.layout.fragment_profile) {
2    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
3        view.findViewById<Button>(R.id.refreshButton).setOnClickListener {
4            (requireActivity() as ProfileActivity).refreshProfile()
5        }
6    }
7}

This is not automatically wrong. It is fine for strongly coupled screens where the fragment only exists inside one activity. The tradeoff is that the fragment can now crash with ClassCastException if someone reuses it in another host. It is also harder to preview or unit test because the dependency is concrete rather than abstract.

Use a shared ViewModel for state-driven coordination

If the fragment is not really asking the activity to run a method but is instead publishing an event or state change, a shared ViewModel is often cleaner. This works well when multiple fragments and the activity all react to the same screen-level actions.

kotlin
1class MainActionViewModel : ViewModel() {
2    private val _openDetails = MutableLiveData<Long>()
3    val openDetails: LiveData<Long> = _openDetails
4
5    fun requestOpenDetails(itemId: Long) {
6        _openDetails.value = itemId
7    }
8}
9
10class ListFragment : Fragment(R.layout.fragment_list) {
11    private val actionViewModel: MainActionViewModel by activityViewModels()
12
13    fun onItemSelected(itemId: Long) {
14        actionViewModel.requestOpenDetails(itemId)
15    }
16}
17
18class MainActivity : AppCompatActivity(R.layout.activity_main) {
19    private val actionViewModel: MainActionViewModel by viewModels()
20
21    override fun onCreate(savedInstanceState: Bundle?) {
22        super.onCreate(savedInstanceState)
23        actionViewModel.openDetails.observe(this) { itemId ->
24            startActivity(Intent(this, DetailsActivity::class.java).apply {
25                putExtra("item_id", itemId)
26            })
27        }
28    }
29}

The main benefit is separation of concerns. The fragment publishes intent, and the activity decides how to handle it. That is a better fit for larger screens, navigation-heavy flows, or apps already using Architecture Components.

Common Pitfalls

The biggest mistake is calling activity too early or assuming it is always non-null. A fragment can exist before being attached, and it can outlive the activity reference during configuration changes. Use requireActivity() only when attachment is guaranteed at that point in the lifecycle.

Another problem is storing the activity reference in a non-null field and never clearing it. That can lead to leaks or callbacks hitting the wrong activity instance after recreation. If you keep a reference, assign it in onAttach and clear it in onDetach.

Developers also overuse direct casting. It works quickly, but it silently turns a reusable fragment into a fragment that only works in one host. If that coupling is intentional, document it. If it is not, use an interface or shared ViewModel.

Finally, avoid making the fragment call deeply specific activity methods for business logic. Let the activity handle screen-level concerns and keep domain logic in a ViewModel, use case, or repository layer.

Summary

  • An interface callback is the best default for calling activity behavior from a fragment.
  • A direct cast is acceptable only when the fragment is intentionally tied to one activity.
  • A shared ViewModel is better when the interaction is event-driven or state-driven.
  • Attach host references in onAttach and clear them in onDetach.
  • Keep business logic out of activity-fragment plumbing whenever possible.

Course illustration
Course illustration

All Rights Reserved.