Sobes.tech
Junior

Jak zavolat metodu aktivity z fragmentu?

sobes.tech AI

Odpověď od AI

Existuje několik způsobů, jak volat metodu aktivity z fragmentu, v závislosti na situaci a architektuře:

  1. Přes odkaz na aktivitu:

    Fragment může získat přímou referenci na aktivitu, ke které je připojen.

    // Uvnitř fragmentu
    if (activity is YourActivity) {
        (activity as YourActivity).yourActivityMethod()
    }
    

    Tento způsob je jednoduchý, ale vytváří silnou závislost mezi fragmentem a konkrétní aktivitou.

  2. Přes callback rozhraní:

    Toto je flexibilnější a doporučený způsob. Definuje se rozhraní ve fragmentu, které musí implementovat aktivita.

    // Uvnitř fragmentu
    interface OnYourActivityMethodListener {
        fun onYourActivityMethodCalled()
    }
    
    private var listener: OnYourActivityMethodListener? = null
    
    override fun onAttach(context: Context) {
        super.onAttach(context)
        if (context is OnYourActivityMethodListener) {
            listener = context
        } else {
            throw RuntimeException("$context musí implementovat OnYourActivityMethodListener")
        }
    }
    
    override fun onDetach() {
        super.onDetach()
        listener = null
    }
    
    // Volání metody aktivity z fragmentu
    fun callActivityMethod() {
        listener?.onYourActivityMethodCalled()
    }
    
    // Uvnitř aktivity
    class YourActivity : AppCompatActivity(), YourFragment.OnYourActivityMethodListener {
    
        override fun onYourActivityMethodCalled() {
            // Logika, která má být provedena v aktivitě
        }
    
        // ... zbytek kódu aktivity
    }
    

    Tento přístup činí fragment znovu použitelnějším, protože závisí na kontraktu (rozhraní), nikoliv na konkrétní třídě aktivity.

  3. Přes ViewModel (doporučeno pro složitější interakce):

    Použití společného ViewModel mezi fragmentem a aktivitou umožňuje výměnu dat a událostí bez přímých odkazů na sebe.

    // Společný ViewModel
    class SharedViewModel : ViewModel() {
        private val _callActivityMethodEvent = MutableLiveData<Event<Unit>>()
        val callActivityMethodEvent: LiveData<Event<Unit>> = _callActivityMethodEvent
    
        fun triggerActivityMethod() {
            _callActivityMethodEvent.value = Event(Unit)
        }
    }
    
    // Obalová třída pro LiveData pro zpracování událostí pouze jednou
    open class Event<out T>(private val content: T) {
        var hasBeenHandled = false
            private set // Umožňuje čtení zvenčí, zápis ne
    
        /**
         * Vrací obsah a zabraňuje jeho opětovnému použití.
         */
        fun getContentIfNotHandled(): T? {
            return if (hasBeenHandled) {
                null
            } else {
                hasBeenHandled = true
                content
            }
        }
    
        /**
         * Vrací obsah i po jeho zpracování.
         */
        fun peekContent(): T = content
    }
    
    // Uvnitř fragmentu
    private val sharedViewModel: SharedViewModel by activityViewModels() // Použití activityViewModels()
    
    // Volání metody aktivity přes ViewModel
    fun callActivityMethod() {
        sharedViewModel.triggerActivityMethod()
    }
    
    // Uvnitř aktivity
    private val sharedViewModel: SharedViewModel by viewModels()
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...
    
        sharedViewModel.callActivityMethodEvent.observe(this, Observer { event ->
            event.getContentIfNotHandled()?.let {
                // Logika, která má být provedena v aktivitě
            }
        })
    }
    

    Tento přístup odpovídá doporučením architektonických komponent a usnadňuje testování.

Volba metody závisí na složitosti interakce. Pro jednoduché případy postačí přímé volání nebo rozhraní. Pro složitější scénáře, zejména spojené s přenosem dat, je vhodnější použít ViewModel.