Sobes.tech
Junior

Cum se apelează metoda activității dintr-un fragment?

sobes.tech AI

Răspuns de la AI

Există mai multe moduri de a apela metoda activității dintr-un fragment, în funcție de situație și arhitectură:

  1. Prin referință la activitate:

    Fragmentul poate obține o referință directă la activitatea la care este atașat.

    // În interiorul fragmentului
    if (activity is YourActivity) {
        (activity as YourActivity).yourActivityMethod()
    }
    

    Această metodă este simplă, dar creează o dependență puternică între fragment și o activitate specifică.

  2. Prin intermediul unei interfețe callback:

    Este o metodă mai flexibilă și recomandată. Se definește o interfață în fragment, pe care activitatea trebuie să o implementeze.

    // În interiorul fragmentului
    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 trebuie să implementeze OnYourActivityMethodListener")
        }
    }
    
    override fun onDetach() {
        super.onDetach()
        listener = null
    }
    
    // Apelarea metodei activității din fragment
    fun callActivityMethod() {
        listener?.onYourActivityMethodCalled()
    }
    
    // În interiorul activității
    class YourActivity : AppCompatActivity(), YourFragment.OnYourActivityMethodListener {
    
        override fun onYourActivityMethodCalled() {
            // Logica care trebuie executată în activitate
        }
    
        // ... restul codului activității
    }
    

    Această abordare face fragmentul mai reutilizabil, deoarece depinde de un contract (interfață), nu de o clasă specifică de activitate.

  3. Prin ViewModel (recomandat pentru interacțiuni mai complexe):

    Utilizarea unui ViewModel comun între fragment și activitate le permite să schimbe date și evenimente, fără referințe directe unul la celălalt.

    // ViewModel comun
    class SharedViewModel : ViewModel() {
        private val _callActivityMethodEvent = MutableLiveData<Event<Unit>>()
        val callActivityMethodEvent: LiveData<Event<Unit>> = _callActivityMethodEvent
    
        fun triggerActivityMethod() {
            _callActivityMethodEvent.value = Event(Unit)
        }
    }
    
    // Clasa wrapper pentru LiveData pentru gestionarea evenimentelor unice
    open class Event<out T>(private val content: T) {
        var hasBeenHandled = false
            private set // Permite citirea externă, dar nu și scrierea
    
        /**
         * Returnează conținutul și împiedică utilizarea sa din nou.
         */
        fun getContentIfNotHandled(): T? {
            return if (hasBeenHandled) {
                null
            } else {
                hasBeenHandled = true
                content
            }
        }
    
        /**
         * Returnează conținutul chiar dacă a fost deja gestionat.
         */
        fun peekContent(): T = content
    }
    
    // În interiorul fragmentului
    private val sharedViewModel: SharedViewModel by activityViewModels() // Folosind activityViewModels()
    
    // Apelarea metodei activității prin ViewModel
    fun callActivityMethod() {
        sharedViewModel.triggerActivityMethod()
    }
    
    // În interiorul activității
    private val sharedViewModel: SharedViewModel by viewModels()
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...
    
        sharedViewModel.callActivityMethodEvent.observe(this, Observer { event ->
            event.getContentIfNotHandled()?.let {
                // Logica care trebuie executată în activitate
            }
        })
    }
    

    Această abordare respectă recomandările componentelor arhitecturale și facilitează testarea.

Alegerea metodei depinde de complexitatea interacțiunii. Pentru cazuri simple, o apelare directă sau o interfață sunt suficiente. Pentru scenarii mai complexe, în special cele legate de transferul de date, utilizarea ViewModel este preferabilă.