0

我正在制作一个应用程序,我想将我的 UI 逻辑分成多个 UI 类,其中 BaseUi 类是生命周期感知的。我使用 Kodein 作为我的 DI,fragment.viewLifecycleOwnerLiveData.observe当我的 ui 类的实例被 Kodein 检索时,我遇到了没有被调用的问题。这是我的片段类:

class ListFragment : Fragment(), DIAware {

    override val di: DI by closestDI()
    override val diTrigger: DITrigger = DITrigger()

    private var binding: FragmentMoviesBinding? = null

    private val fragmentBinding get() = binding

    private val kodeinMoviesUi: MoviesUi by instance() //fragment does not observe viewLifecycleOwnerLiveData

    private val moviesUi: MoviesUi = MoviesUi(this) //fragment now observe viewLifecycleOwnerLiveData

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = FragmentMoviesBinding.inflate(inflater, container, false)
        return binding?.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        diTrigger.trigger()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        binding = null
    }
}

BaseUi 类:

abstract class BaseUi<F : Fragment>(private val fragment: F) : LifecycleObserver {

    init {
        fragment.viewLifecycleOwnerLiveData.observe(fragment, { subscribeToLifecycle() })
    }

    private fun subscribeToLifecycle() {
        fragment.viewLifecycleOwner.lifecycle.addObserver(object : LifecycleObserver {
            @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
            fun onCreate() {
                onViewCreated()
            }
        })
    }

    abstract fun onViewCreated()
}

和 UIModule:

val uiModule = DI.Module("uiModule") {
    bind<ListFragment>() with provider { ListFragment() }
    bind<MoviesUi>() with provider { MoviesUi(instance()) }
}
4

1 回答 1

0

来自https://github.com/Kodein-Framework/Kodein-DI/issues/353的交叉帖子

这是你的问题bind<ListFragment>() with provider { ListFragment() }

您将 与提供者绑定ListFragment,这意味着每次您向容器询问时,它都会创建一个ListFragment. 所以,当你用 注入MoviesUiprivate val kodeinMoviesUi: MoviesUi by instance(),它会得到另一个ListFragment.

我建议您将绑定定义MoviesUi为工厂,等待接收ListFragment实例: bind<MoviesUi>() with factory {fragment: ListFragment -> MoviesUi(fragment) } 然后您可以将其注入ListFragment如下: private val kodeinMoviesUi: MoviesUi by instance(args = this)

于 2021-02-15T05:34:27.197 回答