探究RecyclerView适配器中重载函数的作用以及调用顺序

在使用 RecyclerView 这个强大的滚动控件的时候,需要为它提供一个 Adapter 适配器,这个适配器继承自 RecyclerView.Adapter 这个类,这个类里面有三个抽象方法需要我们去重写,分别是:

  1. onCreateViewHolder(ViewGroup parent, int viewType)
  2. onBindViewHolder(@NonNull ViewHolder viewHolder, int i)
  3. getItemCount()

这三个方法都是由安卓系统去调用的,接下来就讲解一下这三个方法的作用,然后通过日志的方法来探究他们之间的调用顺序。

一:重载函数的作用。

1. onCreateViewHolder(ViewGroup parent, int viewType) 方法。

    这个方法用于加载 RecyclerView 子项的布局,然后返回一个 ViewHolder 对象,ViewHolder  是一个静态内部类,继承自 

  RecyclerView.ViewHolder 类。

2.  onBindViewHolder(ViewHolder viewHolder, int i) 方法.。

    上面那个方法为子项加载布局,这个方法为子项绑定数据。调用这两个方法后,子项就既有了布局又有了数据。

3. getItemCount() 方法。

    用于获取 RecyclerView 一共有多少子项。

二:重载函数的调用顺序。

我们将会通过日志的方法来观察系统是怎么按照怎样的顺序去调用这三个重载函数的。

1. main_activity.xml 布局文件,简单定义 一个 RecyclerView 。(要想使用 RecyclerView  就需要在 build.gradle 文件中导入相应版本的库依赖)

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/text_cycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</android.support.constraint.ConstraintLayout>

2.  RecyclerView 的子项布局文件,text_item.xml。里面只定义了一个 TextView 显示文字。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/text_name"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_gravity="center"
        android:textSize="30sp"/>

</android.support.constraint.ConstraintLayout>

3. MainActivity.java 代码。

package com.example.shinelon.recyclerviewexplore;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private List<String> stringList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //初始化集合数据
        initString();

        //获取RecyclerView的id
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.text_cycler);
        //定义布局管理器
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        //设置recyclerView的布局
        recyclerView.setLayoutManager(layoutManager);

        //定义适配器,传入集合数据
        TextAdapter adapter = new TextAdapter(stringList);
        //为recyclerView设置适配器,即将适配器中数据传入recyclerView中
        recyclerView.setAdapter(adapter);
    }

    //初始化集合数据
    private void initString() {
        for(int i=0; i<4; i++) {
            stringList.add("apple");
            stringList.add("banana");
            stringList.add("orange");
            stringList.add("mango");
            stringList.add("cherry");
        }
    }
}

4. 适配器代码,在重载函数里和 ViewHolder 类构造函数里写入日志语句,在日志文件中可以看到他们的调用先后顺序。

package com.example.shinelon.recyclerviewexplore;

import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.List;

public class TextAdapter extends RecyclerView.Adapter<TextAdapter.ViewHolder>{
    private List<String> stringList;

    //TextAdapter构造函数
    public TextAdapter(List<String> list) {
        stringList = list;
    }

    //ViewHolder类将子项布局中所有控件绑定为一个对象,该对象包含子项布局的所有控件
    static class ViewHolder extends RecyclerView.ViewHolder {
        TextView textView;
        public static int anInt = 0;

        public ViewHolder(View view) {
            super(view);    //父类构造函数
            //获取RecyclerView布局的子项布局中的所有控件id,本次实验只有TextView这一种控件
            textView = (TextView) view.findViewById(R.id.text_name);
            anInt++;
            Log.d("TextAdpter:","加载ViewHolder类:" + anInt);
        }
    }

    //重写构造方法
    //绑定子项布局
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.text_item,null,false);
        Log.d("TextAdpter:","绑定布局");
        return new ViewHolder(view);
    }

    //为每个子项绑定数据
    @Override
    public void onBindViewHolder(@NonNull ViewHolder viewHolder, int i) {
        //获取当前位置的子项对象
        String str = stringList.get(i);
        //从当前子项对象中获取数据,绑定在viewHolder对象中
        viewHolder.textView.setText(str);

        Log.d("TextAdpter:","绑定数据: " + str);
    }

    //获取集合的大小
    @Override
    public int getItemCount() {
        Log.d("TextAdpter:","获取大小: " + stringList.size());
        return stringList.size();
    }
}

5. 结果分析。先上图。

仔细观察上图的日志文件会发现他是有规律的,总是按照 获取大小——>绑定布局——>加载ViewHolder类——>绑定数据。这样一个规律。根据这样的规律,我们就可以知道,系统是按照怎样的顺序来调用这些函数的了。

三:结论。

每当 RecyclerView 的子项出现在屏幕上时或将要出现在屏幕上时,系统会按照如下的顺序调用函数。

1 调用 getItemCount() 方法获取子项的数量。

2 调用 onCreateViewHolder(ViewGroup parent, int viewType) 方法加载每一个子项的布局

3 构造一个 ViewHolder 对象。

4 调用 onBindViewHolder(ViewHolder viewHolder, int i) 方法将数据绑定在 ViewHolder 对象中。

探究 RecyclerView 适配器重载函数的调用顺序就完成了,还要提醒一下的就是,当所有子项加载完后,移出屏幕的子项再次回到屏幕中时,是不会再次构造 ViewHolder 对象的,也就是说这个对象已经被构造过了,再次出现在屏幕中只需要复用就可以了。最后,希望能帮助到大家。

发布了38 篇原创文章 · 获赞 18 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43851639/article/details/90139476