ListView

MainActivity

package a.b.c.lelelistview;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

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

public class MainActivity extends AppCompatActivity{
private List<Bean> data = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savaInstanceState);
setContentView(R.layout.activity_main);
for(int i = 0;i < 100;i++){
Bean bean = new Bean();
bean.setName("lele"+i);
data.add(bean);
}

ListView listView = findViewById(R.id.lv);
listView.setAdapt(new MyAdapter(data,this));
/*setAdapter是ListView的一个方法,用于将适配器(Adapter)设置到ListView上,适配器负责将数据绑定到ListView的视图中。适配器从数据源获取数据,并将每项数据呈现为ListView中的每一个试图项。调用setAdapter后,ListView会通过适配器来管理何显示数据项。*/
listView.setOnItemClickListenner(new AdapterView.OnItemClickListener()){
@override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Log.e("lele", "onItemClick:" + i );
}
}
}
}

Bean
package a.b.c.lelelistview;
public class Bean {

String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

MyAdapter

package a.b.c.lelelistview;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.List;

public class MyAdapter extends BaseAdapter {

private List<Bean> data;
private Context context;

public MyAdapter(List<Bean> data, Context context) {
this.data = data;
this.context = context;
}

@Override
public int getCount() {
return data.size();
}

@Override
public Object getItem(int i) {
return null;
}

@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, View ViewGroup viewGroup){
if(view == null){
view = LayoutInflater.from(context).inflate(R.layout.list_item,viewGroup,false);
}
TextView textView = view.findViewById(R.id.tv);
tevtView.setText(data.get(i).getName());

Log.e("lele","getView: "+i);
return view
}
}
list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:id="@+id/tv"/>
</LinearLayout>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">

<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/lv"/>
</LinearLayout>

优化View getView方法

性能优化

  • 避免重复查找findViewById 是一个性能开销较大的操作。通过缓存视图的引用在 ViewHolder 中,可以避免在每次调用 getView 时重复查找视图。
  • 提高效率ViewHolder 模式可以减少视图查找操作的次数,从而提高列表项的渲染速度和整体性能。
@Override
public View getView(int i, View view, ViewGroup viewGroup){
ViewHolder viewHolder;
if(view == null){
viewHolder = new ViewHolder();
view = LayoutInflater.from(context).inflate(R.layout.list_item,viewGroup,false);
viewHolder.testView = view.findViewById(R.id.tv);
view.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.textView.setText(data.get(i).getName());

Log.e("lele","getView:"+i);
return view;

}

private final class ViewHolder{
TextView textView;
}

RecyclerView

使用时要先导入依赖包

MainActivity
package a.b.c.myrecycleview;

import android.content.Context;
import android.os.Bundle;
import android.os.Parcel;
import android.util.Log;
import android.widget.GridLayout;
import android.widget.LinearLayout;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;

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


public class MainActivity extends AppCompatActivity {
private List<Bean> data = new ArrayList<>();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

for(int i = 0; i < 1000; i++){
Bean bean = new Bean();
bean.setName("lele" + i);
data.add(bean);
}
RecyclerView recyclerView = findViewById(R.id.rv);
/*设置布局管理器:
LinearLayoutManager:RecyclerView 的布局管理器,用于定义列表项的排列方式。这里使用 LinearLayoutManager,它将列表项垂直排列。
recyclerView.setLayoutManager(linearLayoutManager);:将 LinearLayoutManager 设置为 RecyclerView 的布局管理器。*/
//第一种
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(linearLayoutManager);

//第二种
GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3);
recyclerView.setLayoutManager(gridLayoutManager);
//第三种
StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(3, LinearLayout.VERTICAL);
recyclerView.setLayoutManager(staggeredGridLayoutManager);
MyAdapter myAdapter = new MyAdapter(data,this);
recyclerView.setAdapter(myAdapter);

myAdapter.setRecyclerItemClickListener(new MyAdapter.OnRecyclerItemClickListener() {
@Override
public void onRecyclerItemClick(int position) {
Log.e("lele", "onRecyclerItemClick: " + position );
}
});
}
}

MyAdapter

package a.b.c.myrecycleview;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.List;

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

private List<Bean> data;
private Context context;


@NonNull
@Override
public MyAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

View view = View.inflate(context,R.layout.recycleview_item,null);
return new MyViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull MyAdapter.MyViewHolder holder, int position) {
holder.tv.setText(data.get(position).getName());

}

@Override
public int getItemCount() {
return data == null?0:data.size();
}

public class MyViewHolder extends RecyclerView.ViewHolder{
private TextView tv;

public MyViewHolder(@NonNull View itemView) {
super(itemView);
tv = itemView.findViewById(R.id.tv);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(mOnItemClickListener!=null){
mOnItemClickListener.onRecyclerItemClick(getAdapterPosition());
}
}
});
}
}

public MyAdapter(List<Bean> data, Context context) {
this.data = data;
this.context = context;
}

public interface OnRecyclerItemClickListener{
void onRecyclerItemClick(int position);
}

private OnRecyclerItemClickListener mOnItemClickListener;

public void setRecyclerItemClickListener(OnRecyclerItemClickListener listener){
mOnItemClickListener = listener;
}
}

activity_main
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/rv"/>

</LinearLayout>


recycleview_item
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:id="@+id/tv"/>

</LinearLayout>

没问题,我们再一步步解释一下点击 RecyclerView 中项的事件是如何处理的。假设你的 RecyclerView 列表项点击后,在 MainActivity 中有代码来处理这个事件,我们将详细拆解整个过程。

1. 用户点击 RecyclerView 中的项
当用户点击 RecyclerView 中的一个项时,系统会触发这个项的点击事件。

2. 点击事件传递到 ViewHolder
在 MyAdapter 中,你有一个 ViewHolder 类,它代表 RecyclerView 中的每一个项。ViewHolder 的构造函数中设置了点击事件监听器:

java
复制代码
public class MyViewHolder extends RecyclerView.ViewHolder {
private TextView tv;

public MyViewHolder(@NonNull View itemView) {
super(itemView);
tv = itemView.findViewById(R.id.tv);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mOnItemClickListener != null) {
mOnItemClickListener.onRecyclerItemClick(getAdapterPosition());
}
}
});
}
}
解释:
itemView.setOnClickListener:这里为每个 RecyclerView 项的 itemView 设置了点击监听器。
getAdapterPosition():这个方法返回当前项在适配器中的位置(即点击了哪个项)。
mOnItemClickListener.onRecyclerItemClick(getAdapterPosition()):这个方法会被调用,前提是 mOnItemClickListener 不为 null
3. 适配器中的监听器
mOnItemClickListener 是在 MyAdapter 类中定义的一个接口,允许你在外部设置点击事件的处理逻辑。你在 MainActivity 中实现了这个接口:

java
复制代码
public interface OnRecyclerItemClickListener {
void onRecyclerItemClick(int position);
}
4. 设置监听器
在 MainActivity 中,你创建了一个 MyAdapter 实例,并设置了点击事件的监听器:

java
复制代码
MyAdapter myAdapter = new MyAdapter(data, this);
myAdapter.setRecyclerItemClickListener(new MyAdapter.OnRecyclerItemClickListener() {
@Override
public void onRecyclerItemClick(int position) {
Log.e("lele", "onRecyclerItemClick: " + position);
}
});
解释:
setRecyclerItemClickListener:这个方法将 MainActivity 中的监听器实现赋值给 MyAdapter 中的 mOnItemClickListener。
new MyAdapter.OnRecyclerItemClickListener():创建了一个匿名内部类,它实现了 OnRecyclerItemClickListener 接口,并定义了点击事件的具体处理逻辑(这里是打印日志)。
5. 事件处理流程
当用户点击某个 RecyclerView 项时,事件处理流程如下:

触发点击事件:用户点击 RecyclerView 中的一个项。
ViewHolder 中处理点击事件:
itemView 的点击事件触发了 View.OnClickListener 中的 onClick 方法。
onClick 方法检查 mOnItemClickListener 是否为 null。如果不是 null,调用 mOnItemClickListener.onRecyclerItemClick(getAdapterPosition())。
调用 MainActivity 中的点击事件处理方法:
mOnItemClickListener 实际上是 MainActivity 中设置的具体实现。因此,onRecyclerItemClick(int position) 方法会被调用,position 是被点击项的位置。
这会在 MainActivity 中执行你定义的点击事件处理逻辑,例如打印日志。
为什么 mOnItemClickListener 不是 null
在 MainActivity 中,你通过调用 setRecyclerItemClickListener 方法并传递了一个实现了 OnRecyclerItemClickListener 接口的对象来初始化 mOnItemClickListener。
因此,当点击事件发生时,mOnItemClickListener 不为 null,能够正确调用 onRecyclerItemClick 方法。
总结
用户点击 RecyclerView 的项。
ViewHolder 的点击事件监听器触发,并检查 mOnItemClickListener。
mOnItemClickListener 调用 MainActivity 中定义的点击事件处理逻辑。
MainActivity 中的 onRecyclerItemClick 方法执行,处理点击事件。