Adapter适配器

一、Adapter概念解析

1、MVC模式

ea6fd32fe5fb49878cd98cc2321ec1b1.png

关系图解析:

  • Model:通常可以理解为数据,负责执行程序的核心运算与判断逻辑,,通过view获得用户 输入的数据,然后根据从数据库查询相关的信息,最后进行运算和判断,再将得到的结果交给view来显示
  • view:用户的操作接口,说白了就是GUI,应该使用哪种接口组件,组件间的排列位置与顺序都需要设计
  • Controller:控制器,作为model与view之间的枢纽,负责控制程序的执行流程以及对象之间的一个互动 

Adapter适配器在MVC模式中的应用:

虽然MVC模式本身不直接包含Adapter组件,Adapter则是中间的这个Controller的部分: Model(数据) ---> Controller(以什么方式显示到)---> View(用户界面) 。但在MVC的实现和扩展中,经常会用到适配器模式的思想来解决接口不兼容或功能扩展的问题。具体来说,Adapter适配器在MVC模式中的应用可以体现在以下几个方面:

  1. 控制器适配器:
    • 在MVC框架中,控制器(Controller)负责接收用户输入并调用相应的模型和视图。如果框架需要支持多种类型的控制器(例如,基于注解的控制器、实现特定接口的控制器等),可以使用适配器模式来将不同类型的控制器适配到统一的请求处理流程中。
    • 例如,在Spring MVC中,HandlerAdapter就起到了这样的作用,它将不同类型的Controller适配到统一的请求处理接口上,以便DispatcherServlet可以透明地调用任何类型的Controller处理方法。
  2. 模型适配器:
    • 在某些情况下,模型(Model)的数据格式可能与视图(View)所需的格式不匹配。此时,可以使用适配器模式来转换数据格式,使得模型数据能够适配到视图中。
    • 例如,在将数据从数据库传递到Web页面时,可能需要将数据库中的记录转换为JSON或XML等格式,以便在Web页面上展示。此时,可以编写一个适配器来执行这种数据格式的转换。
  3. 视图适配器:
    • 在MVC框架中,视图(View)负责数据的展示和用户交互。如果框架需要支持多种类型的视图(例如,HTML视图、JSON视图等),可以使用适配器模式来将不同类型的数据适配到不同的视图展示方式中。
    • 虽然视图适配器在MVC框架中的直接应用相对较少,但在一些复杂的Web应用程序中,可能会通过自定义视图解析器(ViewResolver)或视图渲染器(ViewRenderer)等方式来实现类似的功能。

 2、Adapter以及继承结构

581bdeff65534b34a67c12bd6c1c6d7d.png

上面是Adapter以及继承结构图了,接着我们介绍一下实际开发中还用到的几个Adapter吧!

  • ArrayAdapter:支持泛型操作,最简单的一个Adapter,只能展现一行文字~
  • SimpleAdapter:同样具有良好扩展性的一个Adapter,可以自定义多种效果!
  • BaseAdapter:抽象类,实际开发中我们会继承这个类并且重写相关方法,用得最多的一个Adapter!
  • SimpleCursorAdapter:用于显示简单文本类型的listView,一般在数据库那里会用到,不过有点过时, 不推荐使用!

二、 常用Adapter的示例教程

1、ArrayAdapter 

首先,创建新项目ArrayAdapter46047e25d46d489b9f40bc6f35f7b131.png

ab3fdf02add64623b77e2d083eff5d2e.png

3776e3fcf4904d8287d4585926540a8a.png

其次,准备布局文件,在原有的acticity_main.xml布局文件中编辑ListView。

代码如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <ListView
        android:id="@+id/ArrayAdapter"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

然后,准备数据,在MainActivity文件中创建了一个ArrayList<String>来存储要显示的数据。在这我使用一个ArrayList对象,并向其中添加50个字符串元素,通过循环,创建了一个包含50个字符串的ArrayList,这些字符串分别是"list_view_0""list_view_49"

代码如下:

ArrayList<String> stringList = new ArrayList<>();  
for (int i = 0; i < 50; i++) {  
    stringList.add("list_view_" + i);  
}

最后,创建ArrayAdapter,使用stringList和一个简单的布局(android.R.layout.simple_list_item_1)来创建ArrayAdapter,并将ArrayAdapter设置到ListView上,以便它能够显示数据。

代码如下:

ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, stringList);

listView.setAdapter(arrayAdapter);

完整MainActivity代码(在此代码中,还设置了一个ListView的点击监听器,以便当用户点击列表项时执行一些操作):

public class MainActivity extends AppCompatActivity {
    private ListView listView;
    private ArrayList<String> stringList;
    private ArrayAdapter<String> arrayAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
        listView = findViewById(R.id.ArrayAdapter);
        stringList = new ArrayList<>();
        for (int i = 0; i < 50; i++) {
            stringList.add("list_view_" + i);
        }
        arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, stringList);
        listView.setAdapter(arrayAdapter);

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                Toast.makeText(MainActivity.this, stringList.get(position), Toast.LENGTH_LONG).show();
            }
        });
    }
}

运行效果如下:

 2e8e6ed9bf044577a9e886c183b02f5d.png     9370f0a325774ea8a3cb32feac9369ee.png

2、SimpleAdapter

首先,创建新项目与上个Array Adapter的一样这里就不多做介绍

其次,准备布局文件,在原有的acticity_main.xml布局文件中编辑ListView。

代码如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

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

</androidx.constraintlayout.widget.ConstraintLayout>

然后,在res/layout目录下创建一个名为list_item.xml的布局文件,定义每个列表项的布局,其中包括一个图片视图(ImageView)和两个文本视图(TextView)。

代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="10dp">

    <ImageView
        android:id="@+id/ivImg"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_marginEnd="16dp"
        android:contentDescription="@string/app_name"
        android:scaleType="centerCrop" />

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tvTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="18sp"
            android:textColor="@android:color/black" />

        <TextView
            android:id="@+id/tvContent"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="4dp"
            android:textSize="14sp"
            android:textColor="@android:color/darker_gray" />
    </LinearLayout>
</LinearLayout>

再将自己需要的图片素材放入 res/drawable目录下(可直接复制粘贴),可根据直接需求重命名。

b928be78ac4d4f9eb33ba93442b3e7e3.png

2fda946899b34f0fa1ba78266ebdeee6.png

最后,修改MainActivity代码,主要为了完成以下事情:

  1. 初始化UI组件:通过布局文件activity_main.xml设置了活动的界面,并在代码中通过findViewById找到了ListView组件。

  2. 准备数据:创建了一个List<Map<String, Object>>来存储列表项的数据,其中每个Map包含了一个图片资源ID、标题和内容。通过循环生成了10个这样的数据项。

  3. 设置适配器:使用SimpleAdapter将准备好的数据绑定到ListView上。SimpleAdapter根据提供的数据源(mapList)、列表项布局(R.layout.list_item)和数据与视图的映射关系(键名到视图ID的映射),自动生成列表项的视图。

  4. 显示列表:将配置好的适配器设置给ListView,从而在界面上显示包含图片、标题和内容的列表。

 代码如下:

public class MainActivity extends AppCompatActivity {
    private ListView listView;
    private List<Map<String,Object>> mapList;
    private Map<String,Object> map;
    private int[] imgs={R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d};
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView=findViewById(R.id.listView);
        mapList=new ArrayList<Map<String,Object>>();
        for (int i=0;i<10;i++){
        map=new HashMap<>();
        map.put("img",imgs[i%imgs.length]);
        map.put("title","这是标题"+i+1);
        map.put("content","这是内容"+i+1);
        mapList.add(map);
        }
        SimpleAdapter simpleAdapter=new SimpleAdapter(
                this,
                mapList,
                R.layout.list_item,
                new String[]{"img","title","content"},
                new int[]{R.id.ivImg,R.id.tvTitle,R.id.tvContent}
        );
        listView.setAdapter(simpleAdapter);
    }
}

运行效果如下:

1260911ec5234e489ef96113e98dd06d.png

3、BaseAdapter

首先,创建适配器类,创建一个新的Java类,并让它继承自BaseAdapter,在这我建立一个名为MyAdapter的适配器。主要是为了连接数据源(articleList)和视图(ListView)。

public class MyAdapter extends BaseAdapter {
    private List<Article> articleList;
    private LayoutInflater layoutInflater;
    private Context context;
    public MyAdapter(Context context, List<Article> articleList){
        this.articleList=articleList;
        this.context=context;
        layoutInflater=LayoutInflater.from(context);
    }
    @Override
    public int getCount() {
        return articleList.size();
    }
    @Override
    public Object getItem(int position) {
        return articleList.get(position);
    }
    @Override
    public long getItemId(int position) {
        return articleList.get(position).getId();
    }
    @Override
    public View getView(int position, View contextView, ViewGroup parent) {
        if (contextView==null) {
            contextView=layoutInflater.inflate(R.layout.list_item,parent,false);
        }
        ImageView imageView=contextView.findViewById(R.id.ivImg);
        TextView tvTitle=contextView.findViewById(R.id.tvTitle);
        TextView tvContent=contextView.findViewById(R.id.tvContent);
        Article article=articleList.get(position);
        imageView.setImageResource(article.getImgId());
        tvTitle.setText(article.getTitle());
        tvContent.setText(article.getInter());
        return contextView;
    }

}
  • 作用:MyAdapter 继承自 BaseAdapter,用于将数据绑定到视图上。
  • 内容:包含文章列表 articleList、布局填充器 layoutInflater 和上下文 context
  • 构造函数:初始化这些数据成员。
  • getCount:返回数据项的数量。
  • getItem:根据位置获取数据项。
  • getItemId:根据位置获取数据项的ID(通常用于唯一标识)。
  • getView:根据位置获取视图,用于显示数据项。

其次,初始化Adapter ,在MainActivity中,初始化视图并设置适配器,使用initView 方法,找到 ListView,创建 MyAdapter 实例,并将适配器设置给 ListView;并准备数据,使用initData 方法准备并初始化要显示的数据创建 articleList 并添加多个 Article 对象。

代码如下:

public class MainActivity extends AppCompatActivity {
    private MyAdapter myAdapter;
    private List<Article> articleList;
    private ListView listView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
        initData();
        initView();
    }

    private void initView() {
        listView=findViewById(R.id.ListView);
        Log.d("TAG",String.valueOf(articleList.size()));
        myAdapter=new MyAdapter(this,articleList);
        listView.setAdapter(myAdapter);
    }

    private void initData() {
        articleList=new ArrayList<>();
        articleList.add(new Article(1,"齿酱","泉州信息工程学院",R.drawable.a));
        articleList.add(new Article(2,"未知","我的桌面", R.drawable.b));
        articleList.add(new Article(3,"糖葫芦","泉州信息工程学院", R.drawable.c));
        articleList.add(new Article(4,"瑶yao","泉州信息工程学院", R.drawable.d));
    }
}

最后,定义数据模型,存储每篇文章的数据Article 类

代码如下:

public class Article {
    private Integer id;
    private String title;
    private String inter;
    private Integer imgId;
    public Article(Integer id, String title, String inter, int imgId){
        this.id=id;
        this.title=title;
        this.inter=inter;
        this.imgId=imgId;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getInter() {
        return inter;
    }

    public void setInter(String inter) {
        this.inter = inter;
    }

    public Integer getImgId() {
        return imgId;
    }

    public void setImgId(Integer imgId) {
        this.imgId = imgId;
    }

}
  • 作用:定义数据模型,用于存储每个文章的数据。
  • 内容:包含 idtitleinterimgId 四个字段及其对应的 getter 和 setter 方法。

(注意,要实现上面BaseAdapter,需在drawable中存入a,b,c,d四张图片,以及在activity_main.xml中创建一个ListView,还需创建一个名为list_item.xml的布局文件,定义每个列表项的布局,此处不多介绍,参考第二个SimpleAdapter中即可完成)

运行效果如下:

8563a48554a24449b4ce4ba374154ccd.png

 三、总结

       作为开发者,我深知Adapter在Android开发中的重要性。它不仅是一个桥梁,连接着数据源与视图,更是实现灵活、可扩展应用的关键组件。本文旨在深入探讨Adapter的概念及其在MVC模式中的应用,并通过具体示例展示常用Adapter的使用。

       首先,我们回顾了MVC模式的基本构成:Model、View和Controller。在这个框架中,Adapter虽然没有直接作为组件出现,但其思想却贯穿于Controller的实现中。Controller作为Model与View之间的枢纽,负责控制程序的执行流程以及对象间的互动。而Adapter,则在这一过程中起到了至关重要的作用,它帮助不同类型的控制器、模型数据以及视图格式之间进行适配,实现了系统的灵活性和可扩展性。

       在MVC框架的扩展中,Adapter的应用主要体现在三个方面:控制器适配器、模型适配器和视图适配器。控制器适配器用于将不同类型的控制器适配到统一的请求处理流程中;模型适配器用于转换模型数据的格式,使其能够适配到视图中;而视图适配器则用于将不同类型的数据适配到不同的视图展示方式中。

       接下来,我们详细探讨了三种常用的Adapter:ArrayAdapter、SimpleAdapter和BaseAdapter。ArrayAdapter是最简单的Adapter,支持泛型操作,但只能展现一行文字。SimpleAdapter则具有良好的扩展性,可以自定义多种效果。而BaseAdapter则是一个抽象类,需要开发者继承并重写相关方法,它提供了最大的灵活性,允许开发者完全控制数据的展示方式。

       通过具体的示例教程,我们展示了如何使用这三种Adapter来展示数据。从简单的ArrayAdapter到复杂的BaseAdapter,每个示例都详细介绍了布局文件的准备、数据的准备以及Adapter的创建和设置过程。这些示例不仅展示了Adapter的基本用法,还演示了如何通过自定义布局和数据模型来实现更加丰富的用户界面。

       总的来说,Adapter是Android开发中不可或缺的一部分。它不仅简化了数据源与视图之间的连接过程,还提供了灵活性和可扩展性,使得开发者能够轻松应对各种复杂的应用场景。通过深入理解Adapter的概念及其在MVC模式中的应用,我们可以更加高效地开发Android应用,为用户提供更加流畅和丰富的体验。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值