Android入门第60天-MVVM中的Databinding与ListView结合使用

news2024/12/26 23:11:34

开篇

        还记得我们进入Listview、GridView都是以一个layout+adapter组合在一起来实现的是吧?那么还记得我们的Adapter的写法么?

        在我们的Adapter里提供了一个bindView方法 。

        在调用时我们需要在Activity里把layout里的控件元素一个个传给这个Adapter。

         在我们的例子里我们的layout里只有两个对象

        那么如果我们现在假设需要实现以下这样的界面(笔者正在制作的基于spring cloud2.0微服务+Android MVVM开源商城,我做完后会把前后端都开源出来。mao-sir.com是笔者拥有的实名域名中的一个)。

        我们可以看到标记1处有两处图片、5处文字。

        再来看标记2处,有一个图片+两个文字。

        如果按照我们之前这个Adapter的写法,岂不是要为这两个layout各写2个Adapter吗?那么我们假设在整个app开发过程中有100个不同的layout呢?那岂不是要变成了Adapter泛滥了吗?

        答案就是:不用这么多Adapter,我们可以使用Databinding来解决大多数问题!

        下面我们就来看如何应对这样的场景。

基于ListView的Databinding

        假设我们需要完成以下这样的一个ListView。

         我们可以看到这样的一个ListView有两个元素构成了它的基本的每一行的Layout。

  • 一个TextView;
  • 一个ImageView;

我们直接来看代码。

代码

先定义一个继承自BaseObservable的User的JavaBean

User.java

package com.mkyuan.android.demo.mvvm;

import android.widget.ImageView;

import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;
import androidx.databinding.BindingAdapter;

import com.bumptech.glide.Glide;

public class User extends BaseObservable {
    public User(String name, int header) {
        this.name = name;
        this.header = header;
    }

    private String name = "";
    private int header;

    @Bindable
    public String getName() {
        return name;
    }

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

    @Bindable
    public int getHeader() {
        return header;
    }

    public void setHeader(int header) {
        this.header = header;
        notifyPropertyChanged(BR.header);
    }

    //自定义属性  headUrl 是自定义的,在xml的imageView中引用
    @BindingAdapter("headId")
    public static void getImage(ImageView view, int headerId) {
        Glide.with(view.getContext()).load(headerId).into(view);
    }
}

        我们可以看到在这个JavaBean里我们依然使用了Glid工具把图片显示到界面上。

dependencies {
    implementation 'com.github.bumptech.glide:glide:4.9.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

定义一个显示在ListiView里每一行用的基本元素的Layout

list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <!-- 设置数据源 data中可以添加多个数据源 -->
    <data>

        <variable
            name="user"
            type="com.mkyuan.android.demo.mvvm.User" />
    </data>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{`姓名:`+user.name}" />

        <ImageView
            android:layout_width="60dp"
            android:layout_height="100dp"
            android:adjustViewBounds="true"
            app:headId="@{user.header}" />

    </LinearLayout>
</layout>

 在这个layout里我们使用了databinding。

定义一个基于Databinding的通用Adapter

MyListAdapter.java

package com.mkyuan.android.demo.mvvm;

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

import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;

import java.util.List;

public class MyListAdapter <T> extends BaseAdapter {
    private Context context;
    private LayoutInflater inflater;
    private int layoutId;
    private int variableId;
    private List<T> list;

    public MyListAdapter(Context context, int layoutId, List<T> list, int resId) {
        this.context = context;
        this.layoutId = layoutId;
        this.list = list;
        this.variableId = resId;
        inflater = LayoutInflater.from(context);
    }


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

    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

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

        ViewDataBinding dataBinding;
        if (convertView == null) {
            dataBinding = DataBindingUtil.inflate(inflater, layoutId, parent, false);
        } else {
            dataBinding = DataBindingUtil.getBinding(convertView);
        }
        dataBinding.setVariable(variableId, list.get(position));
        return dataBinding.getRoot().getRootView();
    }
}

         从代码上看,我们可以看出这个Adapter才是一个“级极Adapter”,所有代码里没有一点和控件元素、多少个控件有关的语句。说白了就是关你多少个控件。。。只要你把layout传进去都可以dataBinding起来。因此这才是一个通用的Adapter,如果没有什么特殊的情况这个Adapter在我们的项目里往往承担着超过90%左右的界面显示的那些活。

在Activity里如何结合layout和adapter

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

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

</LinearLayout>

ActivityMain.java

package com.mkyuan.android.demo.mvvm;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.ListView;

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

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "DemoMVVMList";
    private ListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView = (ListView) findViewById(R.id.listView);
        List<User> list = new ArrayList<User>();
        list.add(new User("张三", R.drawable.icon_1_128));
        list.add(new User("李四", R.drawable.icon_2_128));
        list.add(new User("王五", R.drawable.icon_3_128));
        list.add(new User("赵六", R.drawable.icon_4_128));
        list.add(new User("孙七", R.drawable.icon_5_128));
        list.add(new User("周八", R.drawable.icon_6_128));
        list.add(new User("吴九", R.drawable.icon_7_128));
        MyListAdapter<User> adapter = new MyListAdapter<User>(MainActivity.this,
                R.layout.list_items, list,
                BR.user);
        listView.setAdapter(adapter);


    }
}

运行工程

  1. 记得在build.gradle里需要有dataBinding enabled=true;
  2. 记得在build.gradle里引入Glide组件的依赖;
  3. 记得gradle.properties里需要:userAdroidX=true以及android.enableJetifier=true;
  4. 记得工程要Migrate成AndroidX工程;

        然后运行起来就得到了我们需要的效果

        不妨自己动一下手吧。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/178047.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】文件权限

本期我们来谈谈Linux上的权限&#xff1a;一、权限的概念在生活中我们处处都会遇到权限。权限是什么呢&#xff1f;下面是对于权限的定义&#xff1a;&#x1f4cc;权限&#xff1a;一件事是否允许被“谁”做&#x1f4cc;简化一下就是&#xff1a;权限人事物属性&#x1f4cb;…

【ROS-Navigation】—— Astar路径规划算法解析

文章目录前言1. 导航的相关启动和配置文件1.1 demo01_gazebo.launch1.2 nav06_path.launch1.3 nav04_amcl.launch1.4 nav05_path.launch1.5 move_base_params.yaml1.6 global_planner_params.yaml2. Astar路径规划算法解析2.1 astar.h2.2 astar.cpp参考文献前言 最近在学习ROS的…

《职场求生攻略》学习笔记 Day8

系列文章目录 这是本周期内系列打卡文章的所有文章的目录 《Go 并发数据结构和算法实践》学习笔记 Day 1《Go 并发数据结构和算法实践》学习笔记 Day 2《说透芯片》学习笔记 Day 3《深入浅出计算机组成原理》学习笔记 Day 4《编程高手必学的内存知识》学习笔记 Day 5NUMA内存知…

JavaEE-多线程进阶

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;JavaEE &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录常见的锁策略乐观锁 vs 悲观锁轻量级锁 vs 重量级锁自旋锁 vs 挂起等待锁互斥锁 vs 读写锁公平锁 vs 非公平锁可重入锁 vs 不可…

恶意代码分析实战 8 恶意代码行为

8.1 Lab 11-01 代码分析 首先使用strings进行分析。 Gina是在 msgina.dll中的。 很多有关资源的函数。 关于注册表的函数。 使用ResourceHacker查看。 发现是一个PE文件。 保存为dll文件。 动态分析 启动Promon。 进入注册表查看。 这个恶意代码向磁盘释放了什么&…

分享140个ASP源码,总有一款适合您

ASP源码 分享140个ASP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 140个ASP源码下载链接&#xff1a;https://pan.baidu.com/s/1vxAMMEI7WYS8SAnfbJKdGQ?pwdsas8 提取码&#x…

【ARIXV2209】Multi-Scale Attention Network for Single Image Super-Resolution

【ARIXV2209】Multi-Scale Attention Network for Single Image Super-Resolution 代码&#xff1a;https://github.com/icandle/MAN 这是来自南开大学的工作&#xff0c;将多尺度机制与大核注意机制结合&#xff0c;用于图像超分辨率。 2022年初&#xff0c;大核卷积火了&a…

GBD学习

GBD gbd官网 GDB, the GNU Project debugger 是一个debug工具 支持多种语言&#xff1a; Ada、Assembly、C、C、D、Fortran、Go、 Objective-C、OpenCL、Modula-2、Pascal、Rust 编译文件 首先使用gcc -g .c文件 -o 可执行文件名 进行编译&#xff0c;再使用gdb 可执行文件名…

恶意代码分析实战 10 数据加密

10.1 Lab13-01 比较恶意代码中的字符串&#xff08;字符串命令的输出&#xff09;与动态分析提供的有用信息&#xff0c;基于这些比较&#xff0c;哪些元素可能被加密&#xff1f; 使用WireShark进行动态分析。 有一串字符看起来像是加密的。 使用Strings分析一下。 发现疑似…

KUKA机器人初次通电配置

安全配置 机器人KSS系统里&#xff0c;会提示选择机器人信息的对话框&#xff0c;选择“机器人”按钮&#xff0c;如下&#xff1a; 承接上一步骤&#xff0c;通过示教器确认所有消息&#xff0c;单击消息提示区域&#xff0c;此时一定会弹出如图 所标示的报警消息&#xff0…

【唐诗学习】一、古诗概述

一、古诗概述 为什么要学习古诗词&#xff1f; 古诗词可以陶冶情操&#xff0c;传承文化诗词&#xff0c;其实就是古代的流行歌曲&#xff0c;它们记录着一个个时代的变迁&#xff0c;是历史的旋律。还有一点很重要&#xff1a;同样是记录历史&#xff0c;史书是国家视角&…

零基础学JavaWeb开发(二十二)之 springmvc入门到精通(2)

3、SpringMVC PostMan工具使用 PostMan简介 Postman 是一款功能超级强大的用于发送 HTTP 请求的 Chrome插件 。做web页面开发和测试的人员会使用到该工具其主要特点 特点&#xff1a; 创建 测试&#xff1a;创建和发送任何的HTTP请求&#xff0c;使用PostMan发送 Get、Post、…

Java IO流之字符流详解

字符流概述 字符流的底层其实就是字节流 字符流 字节流 字符集 字符流特点 输入流&#xff1a;一次读一个字节&#xff0c;遇到中文时&#xff0c;一次读多个字节输出流&#xff1a;底层会把数据按照指定的编码方式进行编码&#xff0c;变成字节再写到文件中 使用场景 用于…

学习Go的全部网站集合

给Golang 入门新手整理了一份全部所需网站集合&#xff0c;主要分为三类。 社区类&#xff1a;这类网站是问答、文档、搜索、资源类网站汇总 镜像和安装包类&#xff1a;有些安装包可能无法下载&#xff0c;此处列出一些可下载Go包和镜像的网站。 开发工具&#xff1a;目前流…

代码随想录--栈与队列章节总结

代码随想录–栈与队列章节总结 1.LeetCode232 用栈实现队列 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、pop、peek、empty&#xff09;&#xff1a; 实现 MyQueue 类&#xff1a; void push(int x) 将元素 x 推到队列的末尾i…

2.4.2 浮点型

1.浮点型基本数据类型介绍 浮点类型用于表示有小数部分的数值。在JAVA种有俩种浮点类型&#xff0c;分别是float和double. 类型字节长度位数取值范围float4字节32约 3.40282347E38Fdouble8字节64约 1.79769313486231570E308 double表示这种类型的数值精度是float类型的俩倍&a…

PyCharm中运行LeetCode中代码

Leetcode中题目只需要写函数体里面内容即可。不需要关注输入&#xff0c;输出。 这里拿LeetCode中第一题&#xff0c;两数之和 “给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数…

随机梯度下降算法 入门介绍(最通俗易懂)

文章目录1.什么是梯度2.什么是梯度下降算法3.什么是随机梯度下降算法1.什么是梯度 首先给出高数课程中梯度的定义&#xff1a; 如果对上面的定义没有理解也没有关系&#xff0c;用通俗的语言来说&#xff0c;梯度实际上就是一个向量&#xff0c;向量中的各个元素表示多元函数在…

Java IO流之字节流详解

一、OutputStream输出流 FileOutputStream概述&#xff1a; 操作本地文件的字节输出流&#xff0c;可以把程序中的数据写到本地文件中 书写步骤&#xff1a; ① 创建字节输出流对象 细节1&#xff1a;参数一是字符串表示的路径或者File对象都是可以的 细节2&#xff1a;如果文…

《安富莱嵌入式周报》第300期:几百种炫酷灯阵玩法, USB Web网页固件升级,波士顿动力整活,并联二极管问题,VisualStudio升级,STM32C0

往期周报汇总地址&#xff1a;嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 祝大家春节快乐&#xff01; 视频版&#xff1a; https://www.bilibili.com/video/BV1UY4y1d7C7 《安富莱嵌入式周…