Android实践 — ikan项目(五)

/ 0评 / 0

  前一篇文章简述了项目中所采用MVP模式的实现方式,为了更好的理解项目的架构设计,本篇文章就选了项目中的一个业务功能模块做下讲解。

  我们先看一下presentation层的包结构,以便对presentation层结构有个初识。

如你所见,项目以“功能“为维度划分di、module等包层级,然后再以”模块“为维度划分,比如module层级下feed、notification等包层级。

每个模块一般会有4种职责类。 这里从功能比较简单的Home模块切入将整个流程贯穿起来。

View 职责类

HomeView接口明确View需要展示的数据,定义如下:

interface HomeView : MvpView {

    fun renderFeedSegments(segments: ArrayList<String>)
}

HomeView的具体实现:

class HomeFragment : BaseFragment<HomeView, HomePresenter>(), HomeView {

    @BindView(R.id.movie_feed_view_page_tab_strip)
    @JvmField
    var movieTabStrip: NavigationTabStrip? = null

    @BindView(R.id.movie_view_pager)
    @JvmField
    var movieViewPager: ParallaxViewPager? = null

    @Inject
    override lateinit var presenter: HomePresenter

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

        fragmentComponent().homeComponent(HomeModule()).inject(this)
    }

    override val layout: Int
        get() = R.layout.fragment_home

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

        presenter.loadFeedSegments()
    }

    override fun renderFeedSegments(segments: ArrayList<String>) {
        movieTabStrip?.setTitles(segments)

        movieViewPager?.adapter = FeedViewPagerAdapter(childFragmentManager, getSegmentFeedsFragments(segments))
        movieViewPager?.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {

            override fun onPageScrollStateChanged(state: Int) {
            }

            override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
            }

            override fun onPageSelected(position: Int) {
            }
        })
        movieViewPager?.offscreenPageLimit = movieViewPager?.adapter!!.count
        movieTabStrip?.setViewPager(movieViewPager, 0)
    }

    private fun getSegmentFeedsFragments(segments: ArrayList<String>): MutableList<Fragment> {
        val numbers: MutableList<Fragment> = mutableListOf()
        for (segment in segments) {
            val feedFragment = FeedFragment()
            val bundle = Bundle()
            bundle.putString(FeedFragment.BUNDLE_KEY_SEGMENT, segment)
            feedFragment.arguments = bundle
            numbers.add(feedFragment)
        }

        return numbers
    }
}

Presenter 职责类

HomePresenter接口定义HomeView触发的Action即加载Feed分类,定义如下:

interface HomePresenter : MvpPresenter<HomeView> {

    fun loadFeedSegments()
}

HomePresenter实现如下:

class HomePresenterImpl(private val feedRepositoryManager: FeedRepositoryManager) :
        BasePresenter<HomeView>(), HomePresenter {

    override fun loadFeedSegments() {
        feedRepositoryManager.executeGetSegments(LoadSegmentsObserver())
    }

    private fun loadSegmentsSuccess(segmentEntities: List<SegmentEntity>){
        if (segmentEntities.isNotEmpty()){
            val segments = arrayListOf<String>()

            segmentEntities.iterator().forEach {
                segments.add(it.name)
            }
            view?.renderFeedSegments(segments)
        }
    }

    private fun loadSegmentsError(e: Throwable){}

    inner class LoadSegmentsObserver : MaybeObserver<List<SegmentEntity>>{

        override fun onSubscribe(d: Disposable) {
            addSubscription(d)
        }

        override fun onSuccess(t: List<SegmentEntity>) {
           loadSegmentsSuccess(t)
        }

        override fun onComplete() {
            print("")
        }

        override fun onError(e: Throwable) {
            loadSegmentsError(e)
        }
    }
}

Module 提供被依赖对象的组件

@Module
class HomeModule {

    @Provides
    fun provideHomePresenter(feedRepositoryManager: FeedRepositoryManager): HomePresenter
            = HomePresenterImpl(feedRepositoryManager)
}

Component 表明被依赖对象与依賴对象的组件

被注入目标的组件

@Singleton
@Subcomponent(modules = [HomeModule::class])
interface HomeComponent {

    fun inject(homeFragment: HomeFragment)
}

在HomeFragment中声明被注入的依赖对象:

@Inject
override lateinit var presenter: HomePresenter

在HomeModule中声明提供具体的依赖对象:

@Provides
    fun provideHomePresenter(feedRepositoryManager: FeedRepositoryManager): HomePresenter
            = HomePresenterImpl(feedRepositoryManager)

然后我们需要在HomeFragment中确定整个依赖图:

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

    fragmentComponent().homeComponent(HomeModule()).inject(this)
}

这样依赖对象presenter就会被注入到HomeFragment中,而且在HomePresenterImpl中我们持有FeedRepositoryManager引用,也就是说我们已经将MVP各个职责类串联起来了。

发表评论

电子邮件地址不会被公开。 必填项已用*标注