Android使用MvvM+kotlin实现wanAndroid

  最近在学习mvvm,利用空闲时间写了一个简单版的wanAndroid项目.介绍就不说了,直接上代码.

  1.引入:在App——build.gradle目录引入以下代码即可:

dataBinding{
    enabled true
}

Android使用MvvM+kotlin实现wanAndroid_第1张图片

2.配置gradle.properties

android.useAndroidX=true
android.enableJetifier=true

3.wanAndroid项目主要有首页、知识、导航、项目四个模块,采用MvvM+Kotlin方式

主界面MainActivity代码如下:

/**
 * @作者: njb
 * @时间: 2020/1/13 12:51
 * @描述: 主界面
 */
open class MainActivity : BaseActivity() {
    private val fragmentList: MutableList =
        ArrayList()
    private val strings =
        arrayOf("首页", "知识", "导航", "项目")

    override val layoutId: Int
        get() = R.layout.activity_main

    override fun initView() {
        fragmentList.add(HomeFragment())
        fragmentList.add(KnowledgeFragment())
        fragmentList.add(NavigationFragment())
        fragmentList.add(ProjectFragment())
        viewPager!!.adapter = object : FragmentStateAdapter(this) {
            override fun createFragment(position: Int): Fragment {
                return fragmentList[position]
            }

            override fun getItemCount(): Int {
                return fragmentList.size
            }
        }
        viewPager.offscreenPageLimit = 3
        val tabLayoutMediator = TabLayoutMediator(
            tab_layout,
            viewPager,
            TabConfigurationStrategy { tab: TabLayout.Tab, position: Int ->
                tab.text = strings[position]
            }
        )
        tabLayoutMediator.attach()
        initToolBar()
    }

    private fun initToolBar() {
        setSupportActionBar(toolbar)
        supportActionBar!!.setDisplayHomeAsUpEnabled(false)
        supportActionBar!!.setHomeButtonEnabled(false)
        iv_search.setImageResource(R.drawable.ic_baseline_search_24)
    }

    override fun addListener() {
        iv_search.setOnClickListener(View.OnClickListener {
            startActivity(
                Intent(
                    this@MainActivity,
                    SearchActivity::class.java
                )
            )
        })
    }
}

4.首页Fragment代码:

/**
 * @作者: njb
 * @时间: 2020/1/10 18:19
 * @描述: 首页
 */
class HomeFragment : Fragment(), CompletedListener {
    private var mBinding: ViewDataBinding? = null
    private var artListAdapter: ArtListAdapter? = null
    private var viewModel: HomeViewModel? = null
    private var layoutManager: LinearLayoutManager? = null
    private var page: Int = 1
    private var viewHead: View? = null
    private var banner: Banner? = null
    private var bannerModel: List? = null
    private var viewModels:BannerViewModel ? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        mBinding = DataBindingUtil.inflate(inflater, R.layout.fm_home, container, false)
        val view = mBinding!!.root
        viewHead = LayoutInflater.from(context).inflate(R.layout.item_home_banner, null)
        initBanner()
        initView(view)
        initListener(view)
        return mBinding!!.root
    }

    /**
     * 初始化view
     */
    private fun initView(view: View) {

        artListAdapter = ArtListAdapter(null)
        layoutManager = LinearLayoutManager(activity!!)
        layoutManager!!.orientation = LinearLayoutManager.VERTICAL
        view.rv_home.layoutManager = layoutManager
        artListAdapter!!.addHeaderView(viewHead)
        view.rv_home.addItemDecoration(DividerDecoration(ContextCompat.getColor(activity!!,R.color.ce7e7e7),2))
        view.rv_home.adapter = artListAdapter
        viewModel = HomeViewModel(artListAdapter!!, this)
        //显示加载动画
        viewModel!!.getArtCircleList(page)

    }

    private fun initBanner() {
        banner = viewHead!!.findViewById(R.id.home_banner)

        //设置banner样式
        banner!!.setBannerStyle(BannerConfig.CIRCLE_INDICATOR)
        //设置图片加载器
        banner!!.setImageLoader(GlideImageLoader())
        //设置banner动画效果
        banner!!.setBannerAnimation(Transformer.Default)
        //设置自动轮播,默认为true
        banner!!.isAutoPlay(true)
        //设置轮播时间
        banner!!.setDelayTime(3000)
        //设置指示器位置(当banner模式中有指示器时)
        banner!!.setIndicatorGravity(BannerConfig.CENTER)
        //banner设置方法全部调用完毕时最后调用
        banner!!.start()
        viewModels = BannerViewModel(banner!!,this)
        viewModels!!.getBannerList()
    }

    /**
     * 初始化事件
     */
    private fun initListener(view: View) {
        artListAdapter!!.setOnItemClickListener{
            listener,View,position ->
            Intent(context, WebViewActivity::class.java).run {
                putExtra(AppConstant.WEBVIEW_TITLE_KEY, artListAdapter!!.data[position].title)
                putExtra(AppConstant.WEBVIEW_ID_KEY, artListAdapter!!.data[position].id)
                putExtra(AppConstant.WEBVIEW_URL_KEY, artListAdapter!!.data[position].link)
                startActivity(this, null)
            }
        }

        view.rf_home.setOnRefreshListener {
            page = 1
            viewModel!!.getArtCircleList(page)
            view.rf_home.finishRefresh(200)
        }
        view.rf_home.setOnLoadMoreListener {
            page++
            viewModel!!.getArtCircleList(page)
            view.rf_home.finishLoadMore(200)
        }
    }

    override fun onCompleted() {

    }
}

HomeViewModel

/**
 *@作者: njb
 *@时间: 2020/1/10 17:55
 *@描述:
 */
class HomeViewModel(
    private val adapter: ArtListAdapter,
    private val completedListener: CompletedListener
) {
    private var observer: Observer>? = null
    private var repository = HomeRepository()

    fun getArtCircleList(page:Int) {
        observer = object : Observer> {
            override fun onComplete() {
                completedListener.onCompleted()
            }

            override fun onSubscribe(d: Disposable) {
            }

            override fun onNext(t: BaseModel) {
                if (t.errorCode == 0) {
                    t.data?.let {
                        if(page == 1){
                            adapter.setNewData(it.datas)
                        }else{
                            adapter.addData(it.datas!!)
                        }
                    }
                }
            }

            override fun onError(e: Throwable) {
                completedListener.onCompleted()
            }

        }
        repository.getArcticList(page,
            observer as Observer>
        )

    }
}

首页请求HomeRespository

/**
 *@作者: njb
 *@时间: 2020/1/10 18:00
 *@描述:
 */
class HomeRepository :BaseRepository(){
    fun getArcticList(
        page: Int,
        observer: Observer>) {
        apiServer.articleList(page).subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer)
    }
}

首页文章列表适配器

/**
 *@author: njb
 *@date:   2020/2/11 0011 16:47
 *@desc:   文章列表适配器
 */
class ArtListAdapter (data:List?):
    BaseQuickAdapter(R.layout.item_home,data){

    override fun convert(helper: BaseViewHolder, item: ArticleListModel.DatasBean) {
        val itemBinding = DataBindingUtil.bind(helper.itemView)!!
        itemBinding.homebean = item
        itemBinding.executePendingBindings()
    }
}

首页布局:




    

        

            
        

    

首页Banner加在文章列表头部,Banner广告布局:




    

首页文章列表item布局:




    

        
    


    

        

        

        

            
        

        

        

        

    

 从下图可以看到数据是和视图绑定到一起的,数据发生变化,视图也会改变.其他三个模块的代码都是和首页一样,创建view,绑定视图,请求数据,数据请求成功后直接显示.这里就不写重复赘述了。

Android使用MvvM+kotlin实现wanAndroid_第2张图片

5.遇到的问题:

(1)databinding绑定图片和一般的用法不一样,一般的直接设置背景图片就可以,拿到数据后直接用glide显示,这里是和视图绑定的,所以我们得新建一个图片显示的工具类本文暂定ImageUtil,方法必须和布局中的名称一致,否则会报错.

我们在ImageUitl中新建一个显示首页文章列表图片的方法:

Android使用MvvM+kotlin实现wanAndroid_第3张图片

@BindingAdapter("image_view")
public static void setImageView(ImageView imageView, String urlString) {
    Glide.with(imageView.getContext()).load(urlString).into(imageView);
}

Android使用MvvM+kotlin实现wanAndroid_第4张图片

(2)当实体类有一个list我们好处理,但是如果又嵌套一个的话比较麻烦,本博主也是参考网上的方法,找了很多资料才找到这个办法,刚开始一直获取到的第一个数据.

我们这里就以知识模块为例.返回的数据是一个知识体系列表,然后这个体系列表里面又有一个体系文章标题列表

Android使用MvvM+kotlin实现wanAndroid_第5张图片


    

    
    

    
    
    

下图中一个表示知识体系列表,一个表示体系列表下的栏目列表 

Android使用MvvM+kotlin实现wanAndroid_第6张图片

(3)刚开始在fragment布局中layout设置了宽和高会一直报错

图(1)是错误的写法,会一直报错,这是我作为一个初学者啥也不懂踩的坑

Android使用MvvM+kotlin实现wanAndroid_第7张图片
 图(2)才是正确的写法

Android使用MvvM+kotlin实现wanAndroid_第8张图片

6.实现的效果图如下:

7.最后,项目的完整源码地址:https://gitee.com/jackning_admin/MvvmPlayAndroid

当然,这个小demo还有很多问题需要处理,比如登录注册功能,点赞收藏等等,后面有时间会慢慢补上,欢迎各位大佬前来讨论,指出小弟的问题,如有问题,及时提示,我会及时改正.

 

你可能感兴趣的:(开发实例)