AdapterView是一个抽象类,其派生的子类在用法上十分相似。它继承了ViewGroup,常用的实现类有Spinner、ListView和GridView。其中,Spinner是列表选择框,当需要用户选择的时候,可以提供一个列表将所有可选项列出来,供用户选择;ListView以垂直列表的形式显示所有列表项;GridView用于在界面上按行和列分布的方式来显示多个组件。

Adapter接口及其实现类中,Adapter是一个接口,其派生了ListAdapter和SpinnerAdapter两个子接口。ListAdapter为AbsListView提供列表项,而SpinnerAdapter为AbsSpinner提供列表项。常用的实现类有ArrayAdapter、SimpleAdapter和SimpleCursorAdapter等。其中ArrayAdapter通常用于将数组或List集合的多个值包装成多个列表项;SimpleAdapter用于将List集合的多个对象包装成多个列表项;SimpleCursorAdapter与SimpleAdapter类似,但它与数据库打交道。

Base Adapter是一个抽象类,通常用于被继承,可以对个列表项进行最大限度的定制。

以下是一些示例代码:

ArrayAdapter示例代码:

```java

ArrayAdapter adapter = new ArrayAdapter(this, R.layout.list_item);

adapter.add("Item 1");

adapter.add("Item 2");

adapter.add("Item 3");

listView.setAdapter(adapter);

```

SimpleAdapter示例代码:

```java

SimpleAdapter adapter = new SimpleAdapter(this, dataSet, R.layout.list_item, "key", "value");

listView.setAdapter(adapter);

```

SimpleAdapter 是一个用于在 Android 应用中显示数据列表的适配器。它接收五个参数,分别是:

1. context:整个应用的上下文,用于获取资源和创建视图等操作。

2. data:一个 List> 类型的集合对象,集合中每个 Map<String, ?> 对象生成一个列表项。

3. resource:界面布局 Id,代表一个布局样式文件,该文件作为列表项的组件,控制列表项的外观。

4. from:一个 String[] 类型的参数,该参数决定提取 Map<String, ?> 对象中哪些 key 对应的 value 来生成列表项。

5. to:一个 int[] 类型的参数,该参数决定使用自定义布局中的哪些 View 组件来组合成一个列表项(数组里面的 id 是自定义布局中各个控件的 id,顺序需要与上面的 from 中的顺序对应)。

BaseAdapter 是 Android 中用于为列表提供数据的适配器基类。继承 BaseAdapter 时,必须重写它的四个方法,分别是:

1. getCount():返回 adapter 中数据的个数,即返回列表项的行数。

2. getItem(int position):获得相应数据集合中特定位置的数据项,即返回当前 Item 显示的数据。

3. getItemId(int position):返回 Item 的 Id。

4. getView(int position, View convertView, ViewGroup parent):每一个 Item 项创建时被调用(即每一次 Item 从屏幕外滑进屏幕内的时候调用,或者程序刚开始的时候创建第一屏 Item 的时候调用)。

Adapter 是 Android 中用于为列表提供数据的适配器接口。ViewAdapter 是 Adapter 的一个实现类,用于将数据绑定到具体的视图上。Spinner (列表选择框)是一种常见的列表展示方式,当需要用户选择的时候,可以提供一个列表将所有可选项列出来,供用户选择。

Spinner 的列表项数据的获取方法有两种,一是直接在 XML 布局文件中为 android:entries 属性指定数组作为数据源,二是在代码中通过 AdapterView 的 setAdapter(adapter) 设置。

1. 在 XML 布局中指定数组作为数据源:

首先,在 values 文件下新建一个 arrays.xml 文件,代码如下:

```xml

HTC

iPhone

Samsung

Motorola

Huawei

Nokia

```

然后,在 XML 布局文件中定义一个 Spinner,代码如下:

```xml

android:id="@+id/spinner"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:entries="@array/phone_brand" />

```

以下是重构后的代码:

```xml

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:paddingBottom="@dimen/activity_vertical_margin"

android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

tools:context="net.monkeychan.spinnertest.MainActivity">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:entries="@array/phone_brand" />

``

您好,当设置为 android:spinnerMode=“dropdown” 时,即为下拉样式。如果需要弹出选择框样式,可以将 spinnerMode 属性设置为 android:spinnerMode=“dialog”。此时可以添加属性 android:prompt,为弹出的选择框添加标题。

以下是 XML 文件布局示例:

```xml

android:id="@+id/spinner"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:entries="@array/spinner_entries"

android:prompt="@string/prompt_message" />

```

```xml

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:paddingBottom="@dimen/activity_vertical_margin"

android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

tools:context="net.monkeychan.spinnertest.MainActivity">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:entries="@array/phone_brand"

android:spinnerMode="dialog" />

```

以下是重构后的内容:

```xml

android:layout_width="match_parent"

android:layout_height="match_parent"

android:paddingBottom="@dimen/activity_vertical_margin"

android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

tools:context="net.monkeychan.spinnertest.MainActivity">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:entries="@array/phone_brand"

android:spinnerMode="dialog"

android:prompt="@string/select_phone_brand" />

```

主要的改动有:去掉了不必要的空格和换行符,并将属性值放在一行中。

在提供的代码中,`android:prompt`属性用于设置弹出选择框的标题。需要注意的是,这里只能引用字符串变量,而不能直接写入标题的内容,否则编译时会出错。

要实现这个效果,你可以按照以下步骤操作:

1. 在代码中通过`AdapterView`的`setAdapter(adapter)`方法设置适配器。

2. 创建一个自定义的适配器类,继承自`BaseAdapter`,并实现相应的方法。

3. 在XML文件中布局适配器所需的视图组件。

4. 在代码中实例化适配器对象,并将其设置给`AdapterView`。

下面是一个简单的示例代码:

```java

// MainActivity.java

import android.os.Bundle;

import android.view.View;

import android.widget.AdapterView;

import android.widget.ArrayAdapter;

import android.widget.Button;

import android.widget.Spinner;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

private Button mButton;

private Spinner mSpinner;

private ArrayAdapter mAdapter;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mButton = findViewById(R.id.button);

mSpinner = findViewById(R.id.spinner);

mAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item);

mAdapter.add("选项1");

mAdapter.add("选项2");

mAdapter.add("选项3");

mSpinner.setAdapter(mAdapter);

mSpinner.setPrompt("请选择"); // 设置弹出选择框的标题

mButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

// 点击按钮时触发的选择框显示事件

mSpinner.showDropDown();

}

});

}

}

```

```xml

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"

android:orientation="vertical"

tools:context=".MainActivity">

android:id="@+id/button"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="显示选择框" />

android:id="@+id/spinner"

android:layout_width="match_parent"

android:layout_height="wrap_content" />

```

```java

import android.os.Bundle;

import android.view.View;

import android.widget.AdapterView;

import android.widget.ArrayAdapter;

import android.widget.Spinner;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

private Spinner spinner;

private String[] cities = {"北京", "上海", "广州", "深圳"};

private ArrayAdapter adapter;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

spinner = findViewById(R.id.spinner);

adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, cities);

adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

spinner.setAdapter(adapter);

spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

@Override

public void onItemSelected(AdapterView parent, View view, int position, long id) {

String selectedCity = cities[position];

// 在此处处理选中的城市

}

@Override

public void onNothingSelected(AdapterView parent) {

// 在此处处理没有选中任何城市的情况

}

});

}

}

```

```markdownpublic class MainActivity extends AppCompatActivity {

private String[] location = {

"北京", "广东", "浙江", "四川", "海南", "福建"

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

// 从布局中获取到 Spinner 的实例

Spinner spinner = (Spinner) findViewById(R.id.spinner);

// 创建一个 ArrayAdapter 的对象,并进行初始化

ArrayAdapter arrayAdapter = new ArrayAdapter<>(this,

android.R.layout.simple_spinner_dropdown_item, location);

// 为 Spinner 设置 Adapter

spinner.setAdapter(arrayAdapter);

}

}

```

上面的代码中我们使用了 ArrayAdapter,实际上也可以使用其他 Adapter,如 SimpleAdapter、扩展 BaseAdapter 等,道理是一样的。

GridView 是用于在界面上按行、列分布的方式来显示多个组件的视图。默认情况下,GridView 只显示一列。如果想要显示多列,需要在 XML 布局文件中为属性 `android:numColumns`,或者在代码中使用 `setNumColumns(int)` 方法指定列数。行数则是动态改变的,无需指定。

值得注意的是,虽然`GridView`和`ListView`都继承自`AbsListView`,但是它们之间存在一些差异。尤其是在数据源方面,`GridView`并没有一个名为`android:entries`的属性,这意味着我们不能直接在XML布局文件中为`GridView`指定数据源。相反,我们需要在代码中通过`AdapterView`的`setAdapter(adapter)`方法来设置。

在本示例中,我们将使用`SimpleAdapter`来实现数据的绑定。以水果为例,我们可以将图片看作水果图片,文字看作水果名称。由于图中有行和列,所以我们可以使用`GridView`来实现。从图中可以看出,总共有3列。以下是相应的XML布局文件代码:

```xml

android:id="@+id/grid_view"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:numColumns="3">

```

以上代码定义了一个具有3列的`GridView`。要将具体的水果数据绑定到该视图上,我们需要创建一个自定义适配器类并实现其布局和数据填充逻辑。

```xml

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

android:gravity="center_horizontal"

android:paddingBottom="@dimen/activity_vertical_margin"

android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

tools:context="net.monkeychan.gridviewtest.MainActivity">

android:id="@+id/gridView"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:numColumns="3" />

```

```java

import android.os.Bundle;

import android.widget.ImageView;

import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

ImageView fruitImage = findViewById(R.id.fruit_image);

TextView fruitName = findViewById(R.id.fruit_name);

}

}

```

以下是重构后的代码:

```java

public class MainActivity extends AppCompatActivity {

// 定义一个 int 型数组,用来存放水果对应图片的资源 id

private int[] images = {R.drawable.apple_pic, R.drawable.banana_pic, R.drawable.cherry_pic,

R.drawable.grape_pic, R.drawable.mango_pic, R.drawable.orange_pic, R.drawable.pear_pic,

R.drawable.pineapple_pic, R.drawable.strawberry_pic};

// 定义一个 String 类型的数组,用来存放水果的名称

private String[] names = {"苹果", "香蕉", "樱桃", "葡萄", "芒果", "香橙", "雪梨", "菠萝", "草莓"};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

// 创建一个 List 集合,List 集合的元素是 Map

List> listItems = new ArrayList<>();

for (int i = 0; i < names.length; i++) {

// 创建一个 Map 集合,用来存放水果图片和水果名称

Map listItem = new HashMap<>();

listItem.put("images", images[i]);

listItem.put("names", names[i]);

listItems.add(listItem);

}

// 1. 从布局中获取到 GridView 的实例

GridView gridView = (GridView) findViewById(R.id.gridView);

// 2. 为 GridView 设置适配器

SimpleAdapter simpleAdapter = new SimpleAdapter(

this, listItems, R.layout.gridview_item, new String[]{"images", "names", new int[]{R.id.fruit_image, R.id.fruit_name});

gridView.setAdapter(simpleAdapter);

}

}

```

在上面的代码中,我们使用了 SimpleAdapter。实际上,也可以使用其他 Adapter,如 ArrayAdapter、扩展 BaseAdapter 等,道理是一样的。

ListView 以垂直列表的形式显示所有列表项。与 Spinner 类似,ListView 的列表项数据的获取方法有两种:一是直接在 XML 布局文件中为 android:entries 属性指定数组作为数据源;二是在代码中通过 AdapterView 的 setAdapter(adapter) 设置。

1. 在 XML 布局中指定数组作为数据源

首先,在 values 文件下新建一个 arrays.xml 文件,代码如下:

```xml

HTC

iPhone

Samsung

Motorola

Huawei

Nokia

```

接下来,在 XML 布局文件中定义一个 ListView,代码如下:

```xml

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

android:id="@+id/listview"

android:layout_width="match_parent"

android:layout_height="wrap_content" />

```

请根据以下内容完成重构,并保持段落结构:

```xml

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:paddingBottom="@dimen/activity_vertical_margin"

android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

tools:context="net.monkeychan.listviewtest.MainActivity">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:entries="@array/phone_brand" />

```

2. 在代码中通过 AdapterView 的 setAdapter(adapter) 设置。下面是我们要达到的效果:

注:这次我们使用自定义Adapter。下面我们仍然以水果为例,图片为水果图片,文字为水果名称。

首先,我们需要定义我们自己的Adapter。从图中可以看出,Adapter需要包含文字和图片元素,因此我们可以使用两个List类型的集合来分别存储文字和图片(因为在R.java文件中,图片资源的id是int类型)。下面是自定义Adapter的代码:

```java

public class CustomAdapter extends BaseAdapter {

private Context context;

private List textList;

private List imageList;

public CustomAdapter(Context context, List textList, List imageList) {

this.context = context;

this.textList = textList;

this.imageList = imageList;

}

@Override

public int getCount() {

return textList.size();

}

@Override

public Object getItem(int position) {

return null;

}

@Override

public long getItemId(int position) {

return position;

}

@Override

public View getView(int position, View convertView, ViewGroup parent) {

ViewHolder viewHolder;

if (convertView == null) {

convertView = LayoutInflater.from(context).inflate(R.layout.item_view, parent, false);

viewHolder = new ViewHolder();

viewHolder.textView = (TextView) convertView.findViewById(R.id.text_view);

viewHolder.imageView = (ImageView) convertView.findViewById(R.id.image_view);

convertView.setTag(viewHolder);

} else {

viewHolder = (ViewHolder) convertView.getTag();

}

viewHolder.textView.setText(textList.get(position));

viewHolder.imageView.setImageResource(imageList.get(position));

return convertView;

}

static class ViewHolder {

TextView textView;

ImageView imageView;

}

}

```

下面是重构后的代码:

```java

public class MyListViewAdapter extends BaseAdapter {

private Context mContext;

private int mResource;

private List mImage;

private List mText;

public MyListViewAdapter(Context context, int resource, List image, List text) {

mContext = context;

mResource = resource;

mText = text;

mImage = image;

}

@Override

public int getCount() {

return mText.size();

}

@Override

public Object getItem(int position) {

return mText.get(position);

}

@Override

public long getItemId(int position) {

return position;

}

@Nullable // 在方法返回值上添加注解,表示该方法可能返回 null,使用时需要进行判空处理。

@Override

public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {

// 注意,外部传进来的布局文件中必须要有 id 为 fruit_image 和 fruit_name 的 ImageView、TextView,否则会出现空指针错误。

if (convertView == null) { // 如果传入的 convertView 为 null,说明当前视图还没有被创建过,需要重新创建。

convertView = LayoutInflater.from(mContext).inflate(mResource, null); // 通过 layoutInflater 将指定的 xmlLayout 文件转换成一个 View 对象。并将该对象赋值给 convertView。

}

ImageView imageView = (ImageView) convertView.findViewById(R.id.fruit_image); // 通过 findViewById 从 convertView 这个 viewGroup里面找到对应的控件。并将其赋值给 imageView。这里使用了 Java-style cast,需要注意类型安全问题。如果找不到相应的控件,则会抛出异常。

TextView textView = (TextView) convertView.findViewById(R.id.fruit_name); // 通过 findViewById 从 convertView 这个 viewGroup里面找到对应的控件。并将其赋值给 textView。这里使用了 Java-style cast,需要注意类型安全问题。如果找不到相应的控件,则会抛出异常。

imageView.setImageResource(mImage.get(position)); // 根据当前位置设置图片资源。注意位置从0开始计数。如果当前位置大于等于列表大小,则会越界。如果越界了就会导致程序出现异常。在实际开发中应该避免这种情况的发生。

textView.setText(mText.get(position)); // 根据当前位置设置文本内容。同样注意位置从0开始计数。如果当前位置大于等于列表大小,则会越界。如果越界了就会导致程序出现异常。在实际开发中应该避免这种情况的发生。

return convertView; // 最后返回这个 View。此时的 View 可能已经被修改过了。如果是第一次调用该方法,那么返回的 View 就是我们刚创建的 View;如果是重复调用该方法,那么返回的就是之前已经存在的 View。因为在该方法中并没有对 View 做任何修改操作,所以返回的是原 View 也可以正常工作。

XML 布局文件:

```xml

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:paddingBottom="@dimen/activity_vertical_margin"

android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

tools:context="net.monkeychan.listviewtest.MainActivity">

android:id="@+id/listView"

android:layout_width="match_parent"

android:layout_height="wrap_content" />

```

自定义样式文件(假设为 listitem.xml):

```xml

```

```java

import android.os.Bundle;

import android.view.View;

import android.widget.ImageView;

import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

ImageView fruitImage = findViewById(R.id.fruit_image);

TextView fruitName = findViewById(R.id.fruit_name);

}

}

```

public class MainActivity extends AppCompatActivity {

// 定义一个 int 型数组,用来存放水果图片的 id,图片文件放在 drawable 文件夹下

private int[] images = {R.drawable.apple_pic, R.drawable.banana_pic, R.drawable.cherry_pic, R.drawable.grape_pic, R.drawable.mango_pic, R.drawable.orange_pic, R.drawable.pear_pic, R.drawable.pineapple_pic, R.drawable.strawberry_pic, R.drawable.watermelon_pic};

// 定义一个 String 类型数组,用来存放水果名称

private String[] names = {"苹果", "香蕉", "樱桃", "葡萄", "芒果", "香橙", "雪梨", "菠萝", "草莓", "西瓜"};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

// 从布局中获取到 ListView 的实例

ListView listView = (ListView) findViewById(R.id.listView);

// 创建一个 List 集合,用来存放水果图片

List imagesList = new ArrayList<>();

for (int i = 0; i < images.length; i++) {

imagesList.add(images[i]);

}

// 创建一个 List 集合,用来存放水果名称

List namesList = new ArrayList<>();

for (int i = 0; i < names.length; i++) {

namesList.add(names[i]);

}

// 创建一个 MyListViewAdapter 的对象,并进行初始化

MyListViewAdapter myListViewAdapter = new MyListViewAdapter(this, R.layout.listview_item, imagesList, namesList);

// 为 ListView 设置 Adapter

listView.setAdapter(myListViewAdapter);

}

}

在上述代码中,我们使用了自定义的Adapter。实际上,除了自定义Adapter外,还可以使用其他类型的Adapter,例如ArrayAdapter或者扩展BaseAdapter等,其原理是相同的。

自定义Adapter的优化——提升AdapterView的运行效率

以上面的ListView为例,我们自定义了一个Adapter。让我们来看一下我们的getView()方法:

```java

@Override

public View getView(int position, View convertView, ViewGroup parent) {

// LayoutInflater,布局加载器,用来加载从外部传进来的布局

convertView = LayoutInflater.from(mContext).inflate(mResource, null);

ImageView iv = (ImageView) convertView.findViewById(R.id.fruit_image);

TextView tv = (TextView) convertView.findViewById(R.id.fruit_name);

iv.setImageResource(mImage.get(position));

tv.setText(mText.get(position));

return convertView;

}

```

之前我们提到过,getView()方法是在每个Item项创建时被调用的。在这个方法中,我们每次都重新加载了一次布局。当我们的Item项数量超出屏幕可显示范围时,如果我们在滑动ListView时来回滑动,实际上是多个Item项在反复创建,同一个布局在反复加载。每一次创建Item项、加载布局都会消耗系统资源,对系统来说是很大的开销。当多次滑动后,可能会导致滑动过程中出现卡顿,给用户带来非常不好的体验。那么,有没有可能将之前已经创建好的Item项和已经加载过的布局缓存起来,当再次使用时,只需从缓存中取出使用,而不用再次创建呢?这就是我们接下来要做的事情。

首先,我们需要对布局进行缓存:

在调用 `getView()` 方法时,我们可以先判断缓存中是否存在布局。如果不存在,才去加载布局。`getView()` 方法中的 `convertView` 参数用于将之前加载好的布局进行缓存,以便进行重用。这样就解决了布局缓存的问题。但是,在 `getView()` 方法中,我们每次都会调用 `findViewById()` 方法来获取控件的实例,这部分还可以进一步优化。

其次,我们可以对控件实例进行缓存。为此,我们定义一个名为 `ViewHolder` 的类,它负责缓存控件的实例。当 `convertView` 为空(即缓存中不存在布局)时,我们创建一个 `ViewHolder` 对象,并将控件的实例存储在其中。

下面是改写后的自定义适配器示例代码:

```java

public class CustomAdapter extends BaseAdapter {

private List dataList;

private Context context;

private LayoutInflater inflater;

public CustomAdapter(Context context, List dataList) {

this.context = context;

this.dataList = dataList;

inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

}

@Override

public int getCount() {

return dataList.size();

}

@Override

public Object getItem(int position) {

return dataList.get(position);

}

@Override

public long getItemId(int position) {

return position;

}

@Override

public View getView(final int position, View convertView, final ViewGroup parent) {

ViewHolder viewHolder;

if (convertView == null) { // 如果 convertView 为空,表示需要重新加载布局

convertView = inflater.inflate(R.layout.item_layout, parent, false); // 通过 layoutInflater 将 item_layout.xml 布局文件转换为 View 对象

viewHolder = new ViewHolder(); // 在当前类中定义一个静态内部类作为ViewHolder的引用类型

viewHolder.view = convertView.findViewById(R.id.text_view); // 根据指定的视图 ID 从 convertView 中找到对应的控件实例并存储到 viewHolder.view 中

convertView.setTag(viewHolder); // 将 viewHolder 作为标记保存在 convertView 中,方便后续获取和操作控件实例

} else { // 如果 convertView 不为空,表示可以直接使用缓存的布局和控件实例

viewHolder = (ViewHolder) convertView.getTag(); // 从 convertView 中获取之前缓存的 viewHolder 对象

}

viewHolder.view.setText(dataList.get(position).getText()); // 根据数据更新视图的内容

return convertView; // 将更新后的 convertView 返回给父布局进行显示

}

/**

* 实现缓存控件实例的静态内部类

*/

static class ViewHolder {

TextView view; // 这里假设我们需要缓存的控件是文本视图,可以根据实际情况修改为其他类型的控件实例

}

}

```

```java

public class MyListViewAdapter extends BaseAdapter {

private Context mContext;

private int mResource;

private List mImage;

private List mText;

public MyListViewAdapter(Context context, int resource, List image, List text) {

mContext = context;

mResource = resource;

mText = text;

mImage = image;

}

@Override

public int getCount() {

return mText.size();

}

@Override

public Object getItem(int position) {

return mText.get(position);

}

@Override

public long getItemId(int position) {

return position;

}

@Override

public View getView(int position, View convertView, ViewGroup parent) {

ViewHolder viewHolder;

//判断convertView是否为空

if (convertView == null) {

//LayoutInflater,布局加载器,用来加载从外部传进来的布局

convertView = LayoutInflater.from(mContext).inflate(mResource, null);

//创建ViewHolder的对象

viewHolder = new ViewHolder();

//将控件实例存储在ViewHolder中

viewHolder.iv = (ImageView) convertView.findViewById(R.id.fruit_image);

viewHolder.tv = (TextView) convertView.findViewById(R.id.fruit_name);

//将ViewHolder存储在convertView中,即缓存布局

convertView.setTag(viewHolder);

} else {

//重新获取ViewHolder

viewHolder = (ViewHolder) convertView.getTag();

}

viewHolder.iv.setImageResource(mImage.get(position));

viewHolder.tv.setText(mText.get(position));

return convertView;

}

//创建一个内部类ViewHolder,用来缓存控件实例class ViewHolder{ ImageView iv; TextView tv; }

}

```

您好!AdapterView 和 Adapter 结合使用的步骤如下:

1. 从布局中获取到 AdapterView 的实例,即 findViewById();

2. 创建适合的 Adapter 对象,并进行初始化(根据 Adapter 的构造方法的参数列表传入对应的参数类型);

3. 为 AdapterView 设置 Adapter;

4. 当自定义 Adapter 时,应注意优化方面的问题。

参考资料: