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:
-
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.
-
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.
-
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.