美文网首页
Android开发(27)——RecycleView实战:类似网

Android开发(27)——RecycleView实战:类似网

作者: 让时间走12138 | 来源:发表于2021-04-27 15:18 被阅读0次

    本节内容

    1.数据模块布局

    2.确定数据源

    3.设置item

    4.监听item点击事件

    一、数据模块布局
    1.先从containers里面拖动一个RecycleView布局进来,并设置一下id为mRecycler
    activity_main.xml
    2.在MainActivity里面配置RecyclerView 的样式。第三个参数reverseLayout,要不要反着显示数据,比如说QQ空间,最新也是最后发布的消息一般显示在最前面。但是我们这里不需要反着显示。
     mRecycler.layoutManager = LinearLayoutManager(
                    this,
                    LinearLayoutManager.VERTICAL,
                    false
            )
    
    3.样式搞定之后开始设置适配器(提供具体显示的数据),那么新建一个类来实现Adapter。
    class NewsAdapter :RecyclerView.Adapter<NewsAdapter.NewsViewHolder>() {
         inner  class NewsViewHolder(itemView: View) :RecyclerView.ViewHolder(itemView){
          }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NewsViewHolder { }
    override fun getItemViewType(position: Int): Int {}
    override fun getItemCount(): Int {}
    override fun onBindViewHolder(holder: NewsViewHolder, position: Int) {}
    }
    
    4.因为要向NewsAdapter这个类传递数据,但是如果都交给主类的话,主类的压力就很大。所以我们设置一个中转站仓库,让它来判断数据是来自网络、数据库还是本地。对于中转站来说,只要提供一个加载数据的方法即可。
    • 新建一个名为Repository的类,并设置单例设计模式。
    class Repository private constructor(){
        companion object{
            private var instance = Repository()
            fun getInstance() = instance
        }
    }
    
    • 在这个仓库类里面,还要有获取数据的接口和更改数据的接口
    private fun loadData(){
    }
    
    5.显示新闻的版式有两种,一种左边是标题,右边是图片,下边是点赞数。还有一种上边是标题,下边是图片和点赞数。这三个控件都是分散的,所以我们要把它们封装为一个整体。
    所以我们提供一个类,里面包括标题、图片、点赞数。(因为在这里面什么也不做,所以为数据类)
    • 图片和标题都是不可变的,点赞数是可变的。最后一个参数是版面的类型,我们提供的版式有两种,0表示一种,1表示一种。
    data class NewsModel(val title:String,
                         val imageId:Int,
                         var like:Int,
                         val type:Int
                         )
    
    6.创建一个接口,在里面提供一个 getData()方法。判断数据是从哪个地方加载的(本地/数据库/网络)返回值为数组。
    interface DataInterface {
        fun getData():ArrayList<NewsModel>
    }
    
    7.创建一个LocalUtil类,这个类继承自DataInterface ,在这个类里面加载数据。这里我们自己模拟一下,所以自己写一点死的数据。
    class LocalUtil :DataInterface{
        override fun getData(): ArrayList<NewsModel> {
            //制造数据
            val d1 = NewsModel("安卓开发",R.drawable.cute2,2021,0)
            val d2 = NewsModel("ios开发",R.drawable.cute1,1193,1)
            val d3 = NewsModel("python开发",R.drawable.cute1,3000,0)
            val d4 = NewsModel("Web开发",R.drawable.cute2,150,1)
            return arrayListOf(d1,d2,d3,d4)
        }
    }
    
    二、确定数据源
    1.实现Repository类里面的loadData()方法。获取数据之后,我们要将其保存起来。所以我们在实现这个方法之前要先定义一个变量来保存接收的数据。
    • 它是一个可变数据源,所以要私有化,不能让外部轻易访问。然后封装为不可变的提供给外部使用。
    private val mdatas = mutableListOf<NewsModel>()
    var datas:List<NewsModel> = listOf()
            get() {
            if(field.isEmpty()){
                //如果没有就加载一次,有就直接返回
                loadData()
                field = mdatas.toList()
            }
                return field
        }
    
    2.然后再实现loadData()方法
    private fun loadData(){
            //当前通过localUtil获取数据
           val dataSource:DataInterface = LocalUtil()
            //将获取的数据添加到数据源中
           mdatas.addAll( dataSource.getData())
        }
    
    3.在NewsAdapter里面可以实现 getItemCount()方法了。
    override fun getItemCount(): Int {
            //访问数据中心获取数据的条数
          return  Repository.getInstance().datas.size
        }
    
    三、设置item
    1.在layout里面设置两种xml。直接用约束布局,可以自己任意设置,这个不是重点。我设置的如下图所示。
    news_lent.xml
    news_port.xml
    2.整好之后,我们就需要在NewsAdapter类里面的onCreateViewHolder()方法里面创建一个item,使用LayoutInflater 将xml转化为view。在解析之前,我们要先判断它是哪种类型,所以我们要先写一个方法来设置position对应的那个item类型。
     override fun getItemViewType(position: Int): Int {
            //获取position对应的模型数据
           val model= Repository.getInstance().datas[position]
            return model.type
        }
    
    3.然后就可以在onCreateViewHolder里面解析了。因为我们写了前面那个函数,所以下面这个方法中的参数viewType对应的就是我们前面返回的type。中间的过程系统会自动完成,不用想太多。
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NewsViewHolder {
            val lf =  LayoutInflater.from(parent.context)
            val view:View
            //判断当前这个item的类型
            if(viewType == 0){
               view= lf.inflate(R.layout.news_lent,parent,false)
            }else{
               view= lf.inflate(R.layout.news_port,parent,false)
            }
            return NewsViewHolder(view)
        }
    
    4.在NewsViewHolder方法里面,获取每个控件。mTitle是给TextView设置的id,后面两个也一样。
    inner  class NewsViewHolder(itemView: View) :RecyclerView.ViewHolder(itemView){
               //从当前view中 获取每个控件
            val titleTextView = itemView.findViewById<TextView>(R.id.mTitle)
            val iconImageView = itemView.findViewById<ImageView>(R.id.mIcon)
            val likeTextView = itemView.findViewById<TextView>(R.id.mLike)
         
        }
    
    5.然后在onBinderView方法里面,把它们都解析出来。
    override fun onBindViewHolder(holder: NewsViewHolder, position: Int) {
            //获取position对应的模型数据
            val model = Repository.getInstance().datas[position]
            holder.titleTextView.text = model.title
            holder.iconImageView.setImageResource(model.imageId)
            holder.likeTextView.text = model.like.toString()
    
            }
        }
    
    6.在MainActivity里面设置一下适配器
    mRecycler.adapter = NewsAdapter()
    
    7.然后运行一下,得到如下结果。
    结果
    • 出现这种情况,我们只要把约束布局的高度改为wrap_content即可(两个xml的约束布局高度都要改),然后得到了以下结果。这个是可以往下滑动的。
    第二个结果
    四、监听item点击事件
    1.在newsAdapter类里面的onBindViewHolder方法里面,给itemView设置一个点击事件。
     holder.itemView.setOnClickListener{
            }
    
    2.如果在响应点击事件之后需要进行界面跳转,那么要把事件传给MainActivity然后再调用startActivity方法,这两个类之间就存在一个回调。
    • 所以我们先在newsAdaper类里面定义一个回调参数。
    var callBack:((Int)->Unit)? = null
    
    • 然后在init里面进行回调。
       callBack?.let {
                    it(position)
                }
    
    3.在MainActivity里面再重新设置一下适配器,并实现回调。
    val adapter = NewsAdapter()
            adapter.callBack = {
                startActivity(Intent(this,news2::class.java))
            }
            mRecycler.adapter = adapter
    
    • 之后运行程序,打开之后点击画面,就会进行跳转
    4.如果觉得这样很麻烦的话,可以在NewsViewHolder类里面定义一个变量来记录位置
     var mPosition = 0
    
    • 然后在onBindViewHolder类里面把position赋值给它
     holder.mPosition = position
    
    • 最后回到NewsViewHolder类里面,设置一下监听器。
    init {
               itemView.setOnClickListener{
                   callBack?.let {
                       it(mPosition)
                   }
               }
           }
    

    相关文章

      网友评论

          本文标题:Android开发(27)——RecycleView实战:类似网

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