Sobes.tech
Junior

Kako pozvati metodu aktivnosti iz fragmenta?

sobes.tech АИ

Одговор од АИ

Postoji nekoliko načina za pozivanje metode aktivnosti iz fragmenta, u zavisnosti od situacije i arhitekture:

  1. Preko reference na aktivnost:

    Fragment može dobiti direktnu referencu na aktivnost na koju je povezan.

    // Unutar fragmenta
    if (activity is YourActivity) {
        (activity as YourActivity).yourActivityMethod()
    }
    

    Ovaj način je jednostavan, ali stvara jaku zavisnost između fragmenta i određene aktivnosti.

  2. Preko callback interfejsa:

    Ovo je fleksibilniji i preporučeniji način. Definiše se interfejs u fragmentu, koji aktivnost mora implementirati.

    // Unutar fragmenta
    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 mora implementirati OnYourActivityMethodListener")
        }
    }
    
    override fun onDetach() {
        super.onDetach()
        listener = null
    }
    
    // Pozivanje metode aktivnosti iz fragmenta
    fun callActivityMethod() {
        listener?.onYourActivityMethodCalled()
    }
    
    // Unutar aktivnosti
    class YourActivity : AppCompatActivity(), YourFragment.OnYourActivityMethodListener {
    
        override fun onYourActivityMethodCalled() {
            // Logika koja treba da se izvrši u aktivnosti
        }
    
        // ... ostatak koda aktivnosti
    }
    

    Ovaj pristup čini fragment ponovo upotrebljivijim, jer zavisi od ugovora (interfejsa), a ne od konkretne klase aktivnosti.

  3. Preko ViewModel-a (preporučuje se za složenije interakcije):

    Korišćenje zajedničkog ViewModel-a između fragmenta i aktivnosti omogućava razmenu podataka i događaja bez direktnih referenci jedno na drugo.

    // Zajednički ViewModel
    class SharedViewModel : ViewModel() {
        private val _callActivityMethodEvent = MutableLiveData<Event<Unit>>()
        val callActivityMethodEvent: LiveData<Event<Unit>> = _callActivityMethodEvent
    
        fun triggerActivityMethod() {
            _callActivityMethodEvent.value = Event(Unit)
        }
    }
    
    // Wrapper klasa za LiveData za obradu događaja koji se dešavaju jednom
    open class Event<out T>(private val content: T) {
        var hasBeenHandled = false
            private set // Omogućava spoljašnje čitanje, ali ne i pisanje
    
        /**
         * Vraća sadržaj i sprečava njegovo ponovno korišćenje.
         */
        fun getContentIfNotHandled(): T? {
            return if (hasBeenHandled) {
                null
            } else {
                hasBeenHandled = true
                content
            }
        }
    
        /**
         * Vraća sadržaj čak i ako je već obrađen.
         */
        fun peekContent(): T = content
    }
    
    // Unutar fragmenta
    private val sharedViewModel: SharedViewModel by activityViewModels() // Korišćenje activityViewModels()
    
    // Pozivanje metode aktivnosti putem ViewModel-a
    fun callActivityMethod() {
        sharedViewModel.triggerActivityMethod()
    }
    
    // Unutar aktivnosti
    private val sharedViewModel: SharedViewModel by viewModels()
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...
    
        sharedViewModel.callActivityMethodEvent.observe(this, Observer { event ->
            event.getContentIfNotHandled()?.let {
                // Logika koja treba da se izvrši u aktivnosti
            }
        })
    }
    

    Ovaj pristup odgovara preporukama arhitektonskih komponenti i olakšava testiranje.

Izbor metode zavisi od složenosti interakcije. Za jednostavne slučajeve, odgovaraju direktni poziv ili interfejs. Za složenije scenarije, posebno one povezane sa prenosom podataka, preporučuje se korišćenje ViewModel-a.