Есть ли у Kotlin способ делегировать реализацию интерфейса другому классу? - PullRequest
0 голосов
/ 28 августа 2018

Я использую одно действие и три фрагмента для своего приложения

Каждый фрагмент имеет интерфейс, который используется для связи с логикой

действие реализует этот интерфейс и вызывает логический объект (постоянный фрагмент) с теми же аргументами, поэтому это выглядит примерно так:

class Child : Fragment() {

     private fun userInteraction() {
          (activity as? ChildInteraction)?.askStuff()
     }

     interface ChildInteraction {
          fun askStuff():Unit
     }


}


class ParentActivity : AppCompatActivity(), ChildInteraction {

    override fun askStuff() {
        (supportFragmentManager.findFragmentByTag("LOGIC") as? ChildInteraction).askStuff()
    }
}


class LogicFragment : Fragment(), ChildInteraction {

     override fun askStuff() {
         //do some work here
     }

 }

Дело в том, что в каждом взаимодействии есть 5-10 методов, и все, что делает ParentActivity, - это передает сообщение, есть ли способ упростить передачу?

Я знаю, что вы не можете сделать это на Java, но я надеялся, что у Котлина есть способ сделать это

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Теперь я знаю, что это, вероятно, то, что работает для меня, поэтому я все равно приму другой ответ, и потому что он научил меня чему-то, чего я не знал.

Но после некоторой работы способ, которым я справился, был таким:

Фрагмент, который прикреплен, выглядит так:

class Child : Fragment() {

    private var parent: ChildInteraction? = null

    override fun onAttach(context: Context?) {
        super.onAttach(context)
        //this should throw an exception if it is not implemented correctly
        parent = (context as LogicProvider).logic!! as Child.ChildInteraction
    }

    private fun userInteraction() {
        parent!!.askStuff()
    }

    interface ChildInteraction {
        fun askStuff():Unit
    }
}

Тогда у меня есть LogicProvider интерфейс, подобный этому:

interface LogicProvider {
    val logic: Any?
}

и тогда родитель будет реализовывать логические провайдеры, которые будут передавать аргументы

class ParentActivity : AppCompatActivity(), LogicProvider {
  override var logic: Logic? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        var frag: Fragment? = supportFragmentManager.findFragmentByTag("parent_logic")
        if (frag == null) {
            frag = Logic()
            supportFragmentManager.beginTransaction().add(frag, "parent_logic").commitNow()
        }
        logic = frag as Logic
    }

    override fun onPause() {
        super.onPause()
        if (isFinishing)
            supportFragmentManager.beginTransaction().remove(supportFragmentManager.findFragmentByTag("parent_logic")).commitNow()
    }

}

таким образом, логический фрагмент является единственным, который должен реализовывать интерфейсы

class Logic : Fragment(), Child.ChildInteraction, Child2.ChildInteraction2 {
    override fun askStuff() {
        //do stuff here
    }
    override fun askStuff2() {
        //do other stuff here
    }

}
0 голосов
/ 28 августа 2018

Взгляните на setTargetFragment и getTargetFragment. Вот пример связи от фрагмента к фрагменту:

interface ChildInteraction {
    companion object

    fun askStuff()
}

fun ChildInteraction.Companion.wrap(f: Fragment) = (f.targetFragment as? ChildInteraction)

class Child1 : Fragment() {

    private fun userInteraction() {
        ChildInteraction.wrap(this)?.askStuff()
    }
}

class Child2 : Fragment() {

    private fun userInteraction() {
        ChildInteraction.wrap(this)?.askStuff()
    }
}

class LogicFragment : Fragment(), ChildInteraction {

    override fun askStuff() {
        //do some work here
    }
}

class ParentActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val logic ...

        val child1 ...
        child1.setTargetFragment(logic, 0)

        val child2 ...
        child2.setTargetFragment(logic, 0)
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...