Android——adapter解读


前言

  本篇文章将以常用的RecyclerView的适配器为例来,来解读一下adapter,让读者能够更加清晰的了解adapter的实现原理从而灵活运用,本人才疏学浅,有什么理解不到位的,望指正。


一、adapter是什么?

  adapter的中文意思是适配器,作用在于将数据与控件进行适配达到我们想要的结果。AndroidSDK已经为我们写好了相关的具体实现方法,我们只需要根据需求将数据传输到我们自定义的适配器类里面就能达到想要的结果,所以学会灵活运用适配器很重要。

二、适配器解读

1、继承

请认真阅读示例代码的注释部分

  首先,适配器是可以自由改变效果的,所以我们需要基于AndroidSDK为我们写好的适配器父类去重新创建一个属于自己的适配器。

  以RecyclerView的适配器为例,它的适配器父类是在androidx.recyclerview.widget.RecyclerView中。所有我们第一步在创建自己的适配器的时候需要继承自这个适配器父类。。代码如下(示例):

public class MyAdapter extends RecylcerView.Adapter{

/**
 *  1、MyAdapter是我们自己的适配器名称,也是类名。
 *  2、RecyclerView这个类是AndroidSDk为我们提供类RecylcerView控件类其中就包含父类适配器
 *  3、继承自RecyclerView.Adapter,意思就是这个Adapter是RecyclerView这个类的内部类。
 *  4、我们可以通过Ctrl+左击Adapter进入这个类,并找到adapter这个内部类会发现这是一个内部的抽象类
 *  5、这个抽象类是一个泛型,它的类型继承自ViewHolder。所以还需要一个自定义一个ViewHolder继承自ViewHodler
 *
 *  总结:如果不明白上述解释,只需要记住:
 *      ①自定义的这个适配器类需要继承自RecyclerView.Adapter且是一个泛型
 *      ②我们需要自己写一个对象继承自ViewHodler作为泛型的类型
 */
}

注意:上述代码未完成,会报错。

2、对象

请认真阅读示例代码的注释部分

  通过上面的解释,我们知道了,我们需要自定义一个对象来作为泛型的类型。我们知道这个对象继承自ViewHolder。ViewHolder的意思是观点持有者,这个对象的作用是用来包裹控件组的(或者说是一个容器,容纳控件组的)。我们知道,在使用RecyclerView 的时候需要自定义一个布局模型,而这个布局模型里面的所需要用到的控件就是存放在ViewHolder这个对象里面的。下面我们来写一下这个对象。有两种方式,一种是单独写一个类,另一种是写一个内部类,这里我们就以内部类为例。代码如下(示例):

public class MyAdapter extends RecylcerView.Adapter{

class MyViewHodler extends RecyclerView.ViewHodler{
/**
 *  1、这个内部类可以依照上面的分析方法来看,不过多解释
 * 
 *  总结:这个内部类需要继承自RecyclerView类里面的ViewHolder内部类,
 *      与主类不同的是此时内部类仍没有完成仍会报错,我们将鼠标放到红色红线的位置使用快捷键alt+enter
 *      出现错误提示create constructor matching super(创建于super匹配的构造函数)我们需要创建构造方法
 *      根据提示按回车让他自动创建,继续往下看
 */
}

}
public class MyAdapter extends RecylcerView.Adapter{

class MyViewHodler extends RecyclerView.ViewHodler{
	public MyViewHodler(@NonNull View itemView){
		super(itemView);
		/**
		 *  1、此时,我们的内部类已经构造完成
		 *
		 *  类分析:
		 *      1、我们大致看一下这个内部类只有一个带参数的构造方法
		 *      2、这个构造方法带的参数是View(视图)类型,。表明我们在实例化对象的时候需要传一个View进来
		 *      3、有了这个View我们才能通过view.findViewById()这个方法绑定控件,把多个具体的控件打包在一起
		 *      4、需要使用的时候直接从这个MyViewHolder中调用即可,我们继续往下看
		 */
	}
}

}
public class MyAdapter extends RecylcerView.Adapter<MyAdapter.MyViewHolder>{
//这样我们就写好了泛型
//但依旧会报错,因为我们还需要实现这个类的三个方法,通过alt+enter快捷键快速添加

class MyViewHodler extends RecyclerView.ViewHodler{
	public MyViewHodler(@NonNull View itemView){
		super(itemView);

	}
}

}

3、实现方法

请认真阅读示例代码的注释部分

public class MyAdapter extends RecylcerView.Adapter<MyAdapter.MyViewHolder>{
/**
 *  1、我们可以先通过方法名大致解读,这个方法的作用
 *  2、之后再对返回类型和参数进行分析,来了解这个方法
 */

	//作用初识:创建ViewHolder
    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
		/**
		 *  返回值分析:
		 *      1、这里我们可以看到返回的是一个我们自定义的MyViewHodler类型的对象
		 *      2、所以这个方法的主要作用在于将实例化的MyViewHolder对象返回到主类中
		 * 		3、因此需要实例化MyViewHodler方法,需要实例化方法那么就需通过new调用构造方法
		 * 		4、我们在创建类的时候自动创建了他的构造方法,这个构造方法需要一个View参数
		 * 		5、所以我们在这个方法里面就需要创建出View对象,然后作为实参传输到构造方法里面
		 * 		6、这样MyViewHodler对象才能真正找到相应的布局控件。否则,MyViewHodler只会是一个空对象
		 *      
		 *  参数列表分析:
		 *      1、第一个参数是一个ViewGroup(意思是视图组)类型对象,parent(意思是根),这个常用,这个是参数的实参是由AndroidSDK提供
		 *      2、第二个是一个int类型的对象viewType(意思是视图类型):这个一般用不到,看具体情况,我也没用过
		 *      
		 *  总结:这个方法的主要作用在于返回一个实例化对象MyViewHoler(我们定义好的内部类,即 控件容器)
		 */
        return MyViewHolder;
    }
	
	//作用初识:绑定ViewHolder
    @Override
    public void onBindViewHolder(@NonNull MyViewHodler holder, int position) {
		/**
		 *  返回值分析:
		 *      这个方法没有返回值
		 *
		 *  参数列表分析:
		 *      1、第一个参数是MyViewHolder(就是我们自己写的控件容器对象),这个参数的实参是由我们自己提供的,也就是上一个方法onCreateViewHolder返回的
		 *      2、第二个参数是int类型的position(意思是位置),他的实参也是由我们提供,下一个方法会讲解到
		 * 	    3、position的值是由0开始的,也就是说,第一个列表的位置就可以用position == 0来定位,之后就可以对这个列表进行具体操作
		 *      
		 *  总结:这个方法没有返回值类型,说名这个方法的实际作用不在于提供数据或对象,而在于实际功能的提供,再根据参数,我们不难看出他的作用是用来对列表进行数据或事件等的操作,也就是这直接控制显示。
		 */
    }
	
	//作用初识:获取到项数(件数,或者说条目数)
    @Override
    public int getItemCount() {
	/**
	 *  返回值分析:
	 *      1、这个方法的返回值类型为int
	 *      2、说明我们需要返回一个整型数据给主类
	 *      
	 *  参数列表分析:
	 *      这个方法没有参数
	 *      
	 *  总结:从方法名和返回值类型我们可以看出,我们要返回数据的条数给到主类,而上一个方法说到,有一个int类型的position参数,他就是由这个方法的返回值决定上限。
	 */
        return null;
    }



class MyViewHodler extends RecyclerView.ViewHodler{
	public MyViewHodler(@NonNull View itemView){
		super(itemView);
		//这里面主要是对需要操作的控件进行绑定操作,也就是View.findViewById()操作。
	}
}

}

4、实现原理

请认真阅读示例代码的注释部分
  我们已基本构造出了我们自定义的一个适配器,接下来我们来分析以下实现原理,也是这几个方法之间的联系。(以下代码都是定义过了成员变量)代码如下:

private List<News> newsList;
private LayoutInflater layoutInflater;
  • 我们从内部类MyViewHolder来看,他是用来包裹我们需要用到的RecyclerVIew的模型布局的控件,将之打包在MyViewHolder对象中,方便取用。
  • 而想要打包控件,首先我们需要一个View对象,而这个对象从哪里来,就是我们的第一个方法onCreateViewHoilder,我们需要在这个方法里构建一个View然后实例化MyViewHodler对象,将View作为参数传进去。并将这个对象返回到主类。那么此时,我们的内部类MyViewHolder就接收到了我们RecyclerView的模型布局View,就可以对象控件进行绑定、打包操作。代码如下(示例):
 @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    	View view = layoutInflater.inflate(R.layout.list,parent,false);
		/**
		 *  作用分析:
		 *      inflate的作用是动态加载布局
		 *
		 *  参数列表分析:(可以通过快捷键ctrl+p查看参数列表)
		 *      1、第一个参数是@LayoutRes int resource,这是AndroidSDK自定义的一个整数类型,格式为: R.Layout.xml文件名,用来引用资源文件
		 *      2、第二个参数是ViewGrouplei(意思是视图组)类型,我们看到root(意思根)就想到权限。所以他是要我们给引用的布局他的权限或者说应用范围。
		 *      3、而上面我们说到AndroidSDK为我们提供了这个ViewGroup的实参可以通过onCreateViewHodler的形参传过来
		 *      4、第三个参数是布尔类型,声明的参数名是attachToRoot(附加到根),这个参数就是说是否将引用的布局附加到,AndroidSDK为我们提供的ViewGroup(视图组)中,这里只能填false,否则会报错
		 *      5、如果想要了解第三个为true报错的原因可参考这位博主的这篇文章(https://blog.csdn.net/yaolingrui/article/details/7339913),这里不过多解释。
		 */
    	MyViewHolder holder = new MyViewHolder(view);
        return holder;
    }
  • 接下来只剩下两个方法,我们先分析getItemCount方法,这个方法需要返回列表数目,那么列表的数目是由什么决定的呢?就是数据的条数,通常一条数据我们会用一个对象来表达,而数据有很多条,我们就需要用List的泛型来存储这些对象,即数据条数。代码如下(示例):
@Override
public int getItemCount() {
    return newsList.size();
    //list有size可以方法返回集合大小,就是对象的数量,数据条数
}
  • 最后一个方法就是onBingViewHolder,我们已经分析过它的作用是对具体列表进行数据赋值,事件添加等操作,而这个方法里面的参数MyViewHolder就是第一个方法onCreateViewHodler返MyViewHolder,而position参数(位置)则是根据第三个方法getItenCount返回的数据条数来决定的。
  • 以上就是他们的所有联系,而在具体的实现AndroidSDK已经帮我们写好了,我们只要写出如上方法就行了,剩余的Android会自动实现。当然到这里还没有完。我们知道其实这个适配器还需要两个东西,一个是数据也就是List,另一个是RecyclerView所在Activity的LayoutInflate对象。此时这两个都是空的,所以,我们还需要将这两对象传进来。

5 、方法联系

  根据以上分析,构建了以下关系。

在这里插入图片描述

6、创建构造方法

  我们实例化对象的时候是通过关键字new来调用构造器,创建对象实例,一个对象可以有多个构造方法,区别在于参数的不同,构造器一般可以用于初始化对象的成员变量。我们上文提到的两个对象在适配器里是空的,所以需要通过适配器来进行初始化。我们就需要通过实例化对象使用new调用构造方法将这两个对象的实参传递到构造方法用来初始化,类里面的对象。也就是把实参传到适配器中进行初始化。代码如下(示例):

public RecycleView01Adapter(List<News> listNews, LayoutInflater layoutInflater){
    this.listNews = listNews;
    this.layoutInflater  = layoutInflater;
    //this.  是当前类的成员变量,而等号后面的就是参数列表传过来的实参
}

三、总结

  至此,我们就完成了对RecyclerView的适配器的分析,相信通过本次阅读,读者们都能够清晰的了解和使用适配器了,去写其他的适配器也能轻松应对。如有问题或是错误,欢迎评论、探讨、指正。

  • 31
    点赞
  • 85
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
AndroidAdapter 中实时获取 EditText 的值,可以通过监听 的文本改变事件来实现。以下是一个示例: 1. 首先,在你的 Adapter 类中定义一个接口来监听 EditText 的文本改变事件: ```java public interface EditTextChangeListener { void onTextChanged(int position, String text); } ``` 2. 在 Adapter 中添加一个 EditTextChangeListener 成员变量,并提供一个方法用于设置监听器: ```java public class YourAdapter extends RecyclerView.Adapter<YourAdapter.ViewHolder> { private EditTextChangeListener editTextChangeListener; // ... public void setEditTextChangeListener(EditTextChangeListener listener) { this.editTextChangeListener = listener; } // ... } ``` 3. 在 Adapter 的 ViewHolder 类中添加一个 TextWatcher,用于监听 EditText 文本改变事件,并在事件发生时调用监听器的回调方法: ```java public class ViewHolder extends RecyclerView.ViewHolder { private EditText editText; public ViewHolder(View itemView) { super(itemView); editText = itemView.findViewById(R.id.edit_text); editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (editTextChangeListener != null) { editTextChangeListener.onTextChanged(getAdapterPosition(), s.toString()); } } @Override public void afterTextChanged(Editable s) {} }); } } ``` 4. 最后,在你的 Activity 或 Fragment 中,创建 Adapter 的实例,并设置 EditTextChangeListener: ```java YourAdapter adapter = new YourAdapter(); adapter.setEditTextChangeListener(new EditTextChangeListener() { @Override public void onTextChanged(int position, String text) { // 在这里处理 EditText 文本改变事件 // position 是当前 EditText 所在的位置 // text 是 EditText 的当前文本值 } }); ``` 这样,当用户在任何一个 EditText 中输入文本时,都会触发监听器的回调方法,你可以在回调方法中处理 EditText 的实时值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微冷i1104

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值