似乎我找到了解决方法(感谢@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)
我真的希望在注入时具有提供不同处理功能的灵活性 class InfiniteScrollListener,
就像旧代码所做的那样:
infiniteScrollListener = InfiniteScrollListener(
{
presentor.pullDataFromRemoteServer()
},
linearLayout)
而不是
中的硬编码@Module
class PresentorModule {
… …
@Provides
@ViewScope
fun infiniteScrollListener() : InfiniteScrollListener {
return InfiniteScrollListener(
{
presentor()
},
linearLayoutManager())
}
答案 0 :(得分:1)
如果我理解正确,你希望注入InfiniteScrollListener的Class不知道LinearLayoutManager但是要负责编写执行的代码吗?
或者你可以注入你的InfiniteScrollMethod并为它提供一个setter方法。
class InfiniteScrollListener (val layoutManager: LinearLayoutManager) : ...
var func: (() -> Unit)?=null
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
...
func()
...
}
}
然后在你的视图中:
infiniteOnScollListener.func = { code() }
addOnScrollListener(infiniteScrollListener)
另外还有一个注意事项:在你的匕首模块中,不需要直接调用@Provides方法。例如。
@Provides
@ViewScope
fun provideInfiniteScrollListener(presenter:Presenter,linearLayoutManager: LinearLayoutManager) : InfiniteScrollListener {
return InfiniteScrollListener(
{
presenter
},
linearLayoutManager)
}
Dagger将负责提供提供方法的参数。
传入InfiniteScollListener {presentor()}
的函数除了在调用时创建一个新的演示者之外不会做任何事情(如果你不知道并且它不仅仅是为了解决你的解决方案)。
编辑:我想我可能已经理解了你想要做的事情:你希望监听器在你的演示者或其他东西上调用一个函数,而不知道代码吗?
这个怎么样:
@Provides
@ViewScope
fun provideInfiniteScrollListener(@Named("scrollFunc1") func:()->Unit,presenter:Presenter,linearLayoutManager: LinearLayoutManager) : InfiniteScrollListener {
return InfiniteScrollListener(func,linearLayoutManager)
}
@Provides
@Named("scrollFunc1")
fun scrollFunc(presenter:Presenter):()->Unit{
return { presenter.onScrolled() }
}
我认为我对它的含义感到困惑“将该方法的不同实现提供给InfiniteScrollListener”。实际上谁是func的提供者?