美文网首页
Android使用MvvM+kotlin实现简单WanAndro

Android使用MvvM+kotlin实现简单WanAndro

作者: 淡然灬一笑 | 来源:发表于2020-07-13 01:20 被阅读0次

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

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

    dataBinding{

        enabled true

    }

    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<Fragment> =

            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<BannerModel>? = 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<BaseModel<ArticleListModel>>? = null

        private var repository = HomeRepository()

        fun getArtCircleList(page:Int) {

            observer = object : Observer<BaseModel<ArticleListModel>> {

                override fun onComplete() {

                    completedListener.onCompleted()

                }

                override fun onSubscribe(d: Disposable) {

                }

                override fun onNext(t: BaseModel<ArticleListModel>) {

                    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<BaseModel<ArticleListModel>>

            )

        }

    }

    首页请求HomeRespository

    /**

    *@作者: njb

    *@时间: 2020/1/10 18:00

    *@描述:

    */

    class HomeRepository :BaseRepository(){

        fun getArcticList(

            page: Int,

            observer: Observer<BaseModel<ArticleListModel>>) {

            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<ArticleListModel.DatasBean>?):

        BaseQuickAdapter<ArticleListModel.DatasBean,BaseViewHolder>(R.layout.item_home,data){

        override fun convert(helper: BaseViewHolder, item: ArticleListModel.DatasBean) {

            val itemBinding = DataBindingUtil.bind<ItemHomeBinding>(helper.itemView)!!

            itemBinding.homebean = item

            itemBinding.executePendingBindings()

        }

    }

    首页布局:

    <?xml version="1.0" encoding="utf-8"?>

    <layout xmlns:android="http://schemas.android.com/apk/res/android">

        <LinearLayout

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:orientation="vertical">

            <com.ning.mvvmplayandroid.weight.MyRefreshLayout

                android:id="@+id/rf_home"

                android:layout_width="match_parent"

                android:layout_height="match_parent">

                <androidx.recyclerview.widget.RecyclerView

                    android:id="@+id/rv_home"

                    android:layout_width="match_parent"

                    android:layout_height="match_parent" />

            </com.ning.mvvmplayandroid.weight.MyRefreshLayout>

        </LinearLayout>

    </layout>

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

    <?xml version="1.0" encoding="utf-8"?>

    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"

        xmlns:app="http://schemas.android.com/apk/res-auto"

        android:layout_width="match_parent"

        android:layout_height="match_parent">

        <com.youth.banner.Banner

            android:id="@+id/home_banner"

            android:layout_width="match_parent"

            android:layout_height="200dp"

            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

    首页文章列表item布局:

    <?xml version="1.0" encoding="utf-8"?>

    <layout xmlns:tools="http://schemas.android.com/tools"

        xmlns:android="http://schemas.android.com/apk/res/android"

        xmlns:app="http://schemas.android.com/apk/res-auto">

        <data>

            <variable

                name="homebean"

                type="fule.com.playandroidkotlin.ui.model.ArticleListModel.DatasBean" />

        </data>

        <androidx.constraintlayout.widget.ConstraintLayout

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:padding="10dp"

            tools:ignore="MissingConstraints">

            <TextView

                android:id="@+id/tv_username"

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                app:layout_constraintLeft_toLeftOf="parent"

                android:layout_marginRight="20dp"

                android:text="@{homebean.author}"

                android:textColor="@color/colorPrimary"

                android:textSize="12sp" />

            <TextView

                android:id="@+id/tv_time"

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                app:layout_constraintEnd_toEndOf="parent"

                android:text="@{String.valueOf(homebean.niceDate)}"

                android:textColor="@color/colorPrimary"

                android:textSize="12sp" />

            <androidx.cardview.widget.CardView

                android:id="@+id/cv_content"

                android:layout_width="100dp"

                android:layout_height="80dp"

                app:layout_constraintTop_toBottomOf="@+id/tv_username"

                android:layout_marginTop="10dp"

                android:elevation="0dp"

                app:cardCornerRadius="4dp"

                app:cardElevation="0dp">

                <ImageView

                    android:id="@+id/iv_content"

                    android:layout_width="100dp"

                    android:layout_height="80dp"

                    android:scaleType="centerCrop"

                    app:home_image="@{homebean.envelopePic}"/>

            </androidx.cardview.widget.CardView>

            <TextView

                android:id="@+id/tv_content"

                android:layout_width="0dp"

                android:layout_height="wrap_content"

                android:layout_marginStart="12dp"

                android:layout_marginTop="10dp"

                android:ellipsize="end"

                android:gravity="top|start"

                android:lineSpacingExtra="2dp"

                android:maxLines="2"

                android:text="@{homebean.title}"

                android:textColor="@color/black"

                android:textSize="14sp"

                app:layout_constraintLeft_toRightOf="@+id/cv_content"

                app:layout_constraintRight_toRightOf="parent"

                app:layout_constraintTop_toBottomOf="@+id/tv_username" />

            <TextView

                android:id="@+id/tv_type"

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:layout_marginStart="10dp"

                android:layout_marginTop="10dp"

                android:layout_toRightOf="@+id/cv_content"

                android:gravity="center"

                android:padding="4dp"

                android:text="@{homebean.chapterName}"

                android:background="@drawable/shape_article_type_bg"

                android:textColor="@color/white"

                android:textSize="12sp"

                app:layout_constraintLeft_toRightOf="@+id/cv_content"

                app:layout_constraintTop_toBottomOf="@+id/tv_content" />

            <ImageView

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                app:layout_constraintTop_toBottomOf="@+id/tv_content"

                app:layout_constraintEnd_toEndOf="parent"

                android:layout_marginTop="10dp"

                app:srcCompat="@drawable/ic_favorite_black_24dp" />

        </androidx.constraintlayout.widget.ConstraintLayout>

    </layout>

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

    5.遇到的问题:

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

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

    ​​​​​​

    @BindingAdapter("image_view")

    public static void setImageView(ImageView imageView, String urlString) {

        Glide.with(imageView.getContext()).load(urlString).into(imageView);

    }

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

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

    ​<data>

        <variable

            name="knowledge"

            type="fule.com.playandroidkotlin.ui.model.KnowledgeModel.DataBean" />

        <!导入一个list!>

        <import type="java.util.List" />

        <variable

            name="knowList"

            type="List&lt;fule.com.playandroidkotlin.ui.model.ChildrenModel>" />

        <!表示list的位置!>

        <variable

            name="index"

            type="int" />

    </data>

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

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

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

    图(2)才是正确的写法

    6.实现的效果图如下:

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

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

    相关文章

      网友评论

          本文标题:Android使用MvvM+kotlin实现简单WanAndro

          本文链接:https://www.haomeiwen.com/subject/jzsocktx.html