我是靠谱客的博主 开放河马,这篇文章主要介绍Android使用MvvM+kotlin实现简单WanAndroid前言:,现在分享给大家,希望可以做个参考。

前言:

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

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

复制代码
1
2
3
dataBinding{   enabled true }

img

2.配置gradle.properties

复制代码
1
2
android.useAndroidX=true android.enableJetifier=true

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

主界面MainActivity代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/** * @作者: 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代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/** * @作者: 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() { ​   } }

5.HomeViewModel

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/** *@作者: 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>>       ) ​   } }

6.首页请求HomeRespository

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/** *@作者: 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)   } }

7.首页文章列表适配器

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/** *@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()   } }

8.首页布局:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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>

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
<?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>

10.首页文章列表item布局:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<?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>

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

img

12.遇到的问题:

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

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

img

复制代码
1
2
3
4
@BindingAdapter("image_view") public static void setImageView(ImageView imageView, String urlString) {   Glide.with(imageView.getContext()).load(urlString).into(imageView); }

img

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

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

img

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<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>

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

img

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

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

img 图(2)才是正确的写法

img

13.实现的效果图如下:

img

14.最后,项目的完整源码地址:

MvvmPlayAndroid: mvvm玩Android,鸿神wanAndroidApi练手项目,包含5个模块

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

最后

以上就是开放河马最近收集整理的关于Android使用MvvM+kotlin实现简单WanAndroid前言:的全部内容,更多相关Android使用MvvM+kotlin实现简单WanAndroid前言内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(69)

评论列表共有 0 条评论

立即
投稿
返回
顶部