- 在讲ListView的使用之前,需要了解Adapter适配器,也顺便讲一下MVC的原理以及Adapter在其中的作用
- 图解
AdapterView:用户 *** 作接口,GUI,可以想象成用户看到的界面
Model:事务逻辑层,负责执行程序的核心运算和逻辑判断,通过view来获取用户输入的数据,然后根据数据库查询相关 *** 作,将结果返回给view展示
Controller:控制器,view与model之间的枢纽,通过控制程序的执行流程来进行view和model的交互
- 在android中就是充当controller的作用
- 连接view和model的桥梁
- 图解
- 表格说明
简单的ListView实现baseAdapter:抽象类,实际开发中我们一般继承该类并重写相关的方法
ArrayAdapter:支持泛型 *** 作,只能展示一行文字
SimpleAdapter:具有良好扩展性的简单Adapter,可以自定义多种效果
SimpleCursorAdapter:一般在数据库会用到,用来显示简单文本类型的listView(textview或imageView等)
private String[] data = {"Apple","Banana","Orange","Watermelon","Pear", "Grape","Pineapple","Strawberry","Cherry","Mango","Apple","Banana", "Orange","Watermelon","Pear", "Grape","Pineapple","Strawberry","Cherry","Mango"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ArrayAdapteradapter = new ArrayAdapter (this,android.R.layout.simple_list_item_1,data); ListView listView = findViewById(R.id.list_view); listView.setAdapter(adapter); }
实例(定制ListView界面)ArrayAdapter有多个构造函数的重载,需要三个参数(当前上下文/ListView子项布局的id/要适配的数据)
android.R.layout.simple_list_item_1是一个Android内置的布局文件,里面只有一个TextView,可用于简单的显示一段文本
就相当于ListView每一行就是一个TextView
- 定义一个实体类,作为ListView适配器的适配类型
public class Fruit { private String name; private int imageId; public Fruit(String name, int imageId) { this.name = name; this.imageId = imageId; } public String getName() { return name; } public int getImageId() { return imageId; } }
- 为ListView的子项定义一个布局fruit_item.xml
- 创建一个适配器FruitAdapter,继承自ArrayAdapter
重写了父类的一组构造函数,用于将上下文、ListView的子项布局id和数据都传递进来
重写了getView()方法,每个子项被滚动到屏幕内的时候会被调用
在此方法中,首先通过getItem()方法得到当前项的Fruit实例,然后使用LayoutInflater来为子项加载我们传入的布局
LayoutInflater的inflate()有三个参数,分别是子项布局id,父布局,false(表示只让我们在父布局中声明的layout属性生效,但不会为这个view添加父布局。因为一旦view有了父布局,就不能被添加进ListView中了)
public class FruitAdapter extends ArrayAdapter{ private int resourceId; public FruitAdapter(@NonNull Context context, int resourceId, @NonNull List objects) { super(context, resourceId, objects); this.resourceId = resourceId; } @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { //获取当前项的fruit实例 Fruit fruit = getItem(position); View view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false); ImageView imageView = view.findViewById(R.id.image_fruit); TextView textView = view.findViewById(R.id.text_fruit_name); imageView.setImageResource(fruit.getImageId()); textView.setText(fruit.getName()); return view; } }
- 修改MainActivity
initFruits()用于初始化所有的水果数据
在onCreate()里创建FruitAdapter对象,并将FruitAdapter作为适配器传递给listView
private ListfruitList = new ArrayList<>(); @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initFruits(); FruitAdapter adapter = new FruitAdapter(this,R.layout.fruit_item,fruitList); ListView listView = findViewById(R.id.list_view); listView.setAdapter(adapter); } private void initFruits(){ for (int i = 0; i < 2; i++){ Fruit apple = new Fruit("Apple",R.drawable.apple); fruitList.add(apple); Fruit banana = new Fruit("Banana",R.drawable.banana); fruitList.add(banana); Fruit orange = new Fruit("Orange",R.drawable.orange); fruitList.add(orange); Fruit watermelon = new Fruit("Watermelon",R.drawable.watermelon); fruitList.add(watermelon); Fruit pear = new Fruit("Pear",R.drawable.pear); fruitList.add(pear); Fruit grape = new Fruit("Grape",R.drawable.grape); fruitList.add(grape); Fruit pineapple = new Fruit("Pineapple",R.drawable.pineapple); fruitList.add(pineapple); Fruit strawberry = new Fruit("Strawberry",R.drawable.strawberry); fruitList.add(strawberry); Fruit cherry = new Fruit("Cherry",R.drawable.cherry); fruitList.add(cherry); Fruit mango = new Fruit("Mango",R.drawable.mango); fruitList.add(mango); } }
- 提升ListView运行效率
在FruitAdapter里,getView()方法每次都将布局重新加载,当List View快速滚动时,会成为性能的瓶颈
convertView参数用于将之前加载好的布局进行缓存,以便之后可以进行重用
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { //获取当前项的fruit实例 Fruit fruit = getItem(position); View view; if(convertView == null){ view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false); }else { view = convertView; } ImageView imageView = view.findViewById(R.id.image_fruit); TextView textView = view.findViewById(R.id.text_fruit_name); imageView.setImageResource(fruit.getImageId()); textView.setText(fruit.getName()); return view; }
- 继续更好的优化
前一个虽然不会重复去加载布局,但是每次还是会重复调用View的findViewById()方法来获取一次控件的实例
我们可以借助ViewHolder(内部类)来对此进行优化
ViewHolder用于对控件的实例进行缓存
view的setTag方法,将viewHolder对象存储在view中
@NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { //获取当前项的fruit实例 Fruit fruit = getItem(position); View view; ViewHolder viewHolder; if(convertView == null){ view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false); viewHolder = new ViewHolder(); viewHolder.imageView = view.findViewById(R.id.image_fruit); viewHolder.textView = view.findViewById(R.id.text_fruit_name); //将viewHolder储存在View中 view.setTag(viewHolder); }else { view = convertView; //重新获取viewHolder viewHolder = (ViewHolder) view.getTag(); } viewHolder.imageView.setImageResource(fruit.getImageId()); viewHolder.textView.setText(fruit.getName()); return view; } class ViewHolder{ ImageView imageView; TextView textView; }
- 点击事件
使用setOnItemClickListener给listView注册了一个监听器,当用户点击任何一个子项时,都会回调onItemClick()方法,可以通过position参数判断用户点击的哪一个子项
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initFruits(); FruitAdapter adapter = new FruitAdapter(this,R.layout.fruit_item,fruitList); ListView listView = findViewById(R.id.list_view); listView.setAdapter(adapter); listView.setonItemClickListener(new AdapterView.onItemClickListener() { @Override public void onItemClick(AdapterView> adapterView, View view, int position, long id) { Fruit fruit = fruitList.get(position); Toast.makeText(MainActivity.this,fruit.getName(),Toast.LENGTH_SHORT).show(); } }); }
- 源码地址
DoSomeAndroidTest/ListViewTest at main · qricis/DoSomeAndroidTest · GitHub
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)