【发布时间】:2018-02-11 17:26:00
【问题描述】:
似乎我找到了解决方法(感谢@David Medenjak 解释错误),它可以工作,但不确定是否有更好的方法来做到这一点,特别是提供向注入的 InfiniteScrollListener 实例证明不同处理函数的灵活性.当前的解决方案是处理函数在 PresentorModule 中硬编码。为此,我认为这不是解决错误的真正解决方案
@javax.inject.Named("func") kotlin.jvm.functions.Function0<kotlin.Unit> cannot be provided without an @Provides-annotated method.
这是当前的解决方案:
带有ViewScope的子组件,现在它提供了LinearLayoutManager和InfiniteScrollListener,它们是这个范围的单线体
@ViewScope
@Subcomponent(modules = arrayOf(PresentorModule::class))
interface PresentorComponent {
fun inject (fragment: ArticlesFragment)
fun getPresenter(): Presentor
fun getLinearLayoutManager(): LinearLayoutManager
fun getInfiniteScrollListener(): InfiniteScrollListener
}
PresentorModule 提供了linearLayoutManager(依赖于该模块的当前上下文),以及依赖于presentor 和linearLayoutManager 的InfiniteScrollListener,带有hard coded implementation of the handling function
@Module
class PresentorModule {
var mContext: Context
var mPresentor: Presentor
constructor(context: Context) {
mContext = context
mPresentor = Presentor()
}
@Provides
@ViewScope
internal fun context(): Context {// not sure if it has to implement to provide this mContext
return mContext
}
@Provides
@ViewScope
fun presentor() : Presentor {
return mPresentor
}
@Provides
@ViewScope
fun linearLayoutManager() : LinearLayoutManager {
return LinearLayoutManager(mContext)
}
@Provides
@ViewScope
fun infiniteScrollListener() : InfiniteScrollListener {
return InfiniteScrollListener(
{
presentor().pullDataFromRemoteServer()
},
linearLayoutManager())
}
// really would like to have the flexibility of letting the consumer provides the
// handling function to the InfiniteScrollListener instance,
// but don’t know how to do it, so have to hard code the handling function
// in the provider of InfiniteScrollListener listed above
// @Provides
// @ViewScope
// fun infiniteScrollListener(func: () -> Unit, layoutManager: LinearLayoutManager) : InfiniteScrollListener {
// return InfiniteScrollListener(func, layoutManager)
// }
}
InfiniteScrollListener类的定义,它接受一个处理函数,在onScrolled()中调用
class InfiniteScrollListener (val func: () -> Unit,
val layoutManager: LinearLayoutManager) : RecyclerView.OnScrollListener() {
init{
… …
}
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
… …
func()
… …
}
presentorComponent的使用:
private lateinit var presentorComponent: PresentorComponent
var infiniteScrollListener: InfiniteScrollListener? = null
@Inject
lateinit var presentor: Presentor
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
……
//use dagger to inject viewScope presentor
if (MyApp.graph != null) {
presentorComponent = MyApp.graph
.addChildModle(PresentorModule(getActivity()))
presentorComponent
.inject(this)
}
return view
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
articlesList!!.apply {
setHasFixedSize(true)
clearOnScrollListeners()
infiniteScrollListener = presentorComponent.getInfiniteScrollListener()
// old non-injection way to instantiate the InfiniteScrollListener with
// a custom handling function passed in at this moment
// infiniteScrollListener = InfiniteScrollListener(
// {
// presentor.pullDataFromRemoteServer()
// },
// linearLayout)
addOnScrollListener(infiniteScrollListener)
我真的很想在注入时灵活地提供不同的处理功能 类 InfiniteScrollListener,
就像旧代码所做的那样:
infiniteScrollListener = InfiniteScrollListener(
{
presentor.pullDataFromRemoteServer()
},
linearLayout)
而不是硬编码在
@Module
class PresentorModule {
… …
@Provides
@ViewScope
fun infiniteScrollListener() : InfiniteScrollListener {
return InfiniteScrollListener(
{
presentor()
},
linearLayoutManager())
}
【问题讨论】: