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各个职责类串联起来了。

    发表评论

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