Kotlin+DataBinding+MVVM 做ImageView 图片加载 详细教程

该博客主要介绍Android项目搭建与功能实现。项目准备引入DataBinding、MVVM框架、图片浏览框架ImageSelector和图片加载框架Glide。搭建页面包括创建Activity、ViewModel,修改XML和Activity。编写逻辑实现点击按钮改文字、加载网络图片及选择本地图片,还总结了通过DataBinding自定义属性完成图片自动加载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、 项目准备

1. 引入DataBinding
  • 在项目 build.gradle 文件 android 节点下添加
    buildFeatures {
        dataBinding = true // for data binding
    }
2. 引入一个MVVM 框架
    implementation 'com.github.AranAndroid009:CustomView:0ca395ae60'
    implementation 'com.github.AranAndroid009:Mvvm:97b52ee25b'
3. 引入一个图片浏览的框架 ImageSelector:

注: 该框架模仿微信UI 可以兼容android 10
项目地址: https://github.com/donkingliang/ImageSelector
根据项目文档,自己行导入 做好准备工作

    implementation 'com.github.donkingliang:ImageSelector:2.2.1'
4. 引入一个图片加载的框架 Glide
    implementation 'com.github.bumptech.glide:glide:4.12.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'

二、 搭一个页面

1. 创建 一个空的Activity
2. 创建 ViewModel
  class MainVM : BaseViewModel() {
  }
3. 修改XML
  • 布局最外层用 layout 节点包裹 , 此时会自动生成 ActivityMainBinding
 <layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    
 </layout>
  • 添加数据绑定, 让改页面拥有MainVM 的一个实例化对象
 <layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
        <data>
        <import type="android.view.View" />
        <variable
            name="vm"
            type="com.winspread.waterrecord.main.MainVM" />
    </data>
 </layout>
  • 我们给页面添加 一个图片控件和按钮控件
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <import type="android.view.View" />
        <variable
            name="vm"
            type="com.winspread.waterrecord.main.MainVM" />
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".main.MainActivity">

        <ImageView
            android:id="@+id/iv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true" />

        <Button
            android:id="@+id/btn_single"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:text="按钮"/>
    </RelativeLayout>
</layout>
3. 修改 Activity
class MainActivity : BaseActivity<MainVM, ActivityMainBinding>(R.layout.activity_main) {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 让页面vm 获取 MainVM 的实例  
        binding.vm = viewModel
        // 绑定activity生命周期, 如果不绑定可能会出现数据改变页面不变的情况
        binding.lifecycleOwner = this
    }
}

三、 编写逻辑

1. 先写个小功能, 点击按钮, 让按钮文字修改

1.binding.lifecycleOwner = this 上面如果没有写这句绑定会出现点击没有反应
2.btnText 其实变量可以理解为被观察对象,页面去订阅了他改变的事件

  • 在 MainVM 定义个变量和方法
    var btnText = MediatorLiveData<String>()
    fun btnLogin(v: View) {
    	btnText.value = "点击了"
    }
  • 将数据和事件绑定到页面上
        <Button
            android:id="@+id/btn_single"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:onClick="@{(v)->vm.btnLogin(v)}"
            android:text="@{vm.btnText}" />
2. 默认是加载一个网络图片, 点击按钮选择一张本地图片
  • 根据 ImageSelector 项目开发文档 自行导入, 别忘了添加必要的权限
  • 完整 MainVM
class MainVM : BaseViewModel() {

    var btnText = MediatorLiveData<String>()
    var url = MediatorLiveData<String>()
    var uri = MediatorLiveData<Uri>()
    var onClick = MediatorLiveData<String>()

    // 方式一
    fun btnLogin(v: View) {
	//  btnText.value = "点击了"
        onClick.postValue("")
    }
}
  • 完整 MainActivity

class MainActivity : BaseActivity<MainVM, ActivityMainBinding>(R.layout.activity_main) {

    val REQUEST_CODE = 1
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding.vm = viewModel
        binding.lifecycleOwner = this
        initView()
    }

    private fun initView() {
        // 默认显示一个网路图片
        viewModel.url.value = "https://t7.baidu.com/it/u=4162611394,4275913936&fm=193&f=GIF"
        ImageSelector.preload(this)
        // 方式一
        viewModel.onClick.observe(this, Observer {
            ImageSelector
                .builder()
                .useCamera(true) // 设置是否使用拍照
                .setSingle(true)  //设置是否单选
                .canPreview(true) //是否可以预览图片,默认为true
                .start(this, REQUEST_CODE); // 打开相册
        })

        // 方式二
        binding.btnSingle.setOnClickListener({
            ImageSelector
                .builder()
                .useCamera(false) // 设置是否使用拍照
                .setSingle(true)  //设置是否单选
                .canPreview(true) //是否可以预览图片,默认为true
                .start(this, REQUEST_CODE); // 打开相册
        })
    }

    override fun onActivityResult(
        requestCode: Int,
        resultCode: Int,
        data: Intent?
    ) {
        super.onActivityResult(requestCode, resultCode, data)

        if (requestCode == REQUEST_CODE && data != null) {
            //获取选择器返回的数据
            val images: ArrayList<String>? =
                data.getStringArrayListExtra(ImageSelector.SELECT_RESULT)

            viewModel.btnText.value = images?.get(0)
            viewModel.uri.value = UriUtils.getImageContentUri(this, images?.get(0))
        }
    }
}
  • 完整的XML ( 如果使用方式一 需要添加onClick属性 如果使用方式二 请删掉onClick 这行 )
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <import type="android.view.View" />
        <variable
            name="vm"
            type="com.winspread.waterrecord.main.MainVM" />
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".main.MainActivity">

        <ImageView
            android:id="@+id/iv"
            imageUri="@{vm.uri}"
            imageUrl="@{vm.url}"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true" />

        <!--  如果使用方式一 需要添加onClick属性
                如果使用方式二 请删掉onClick 这行 -->
        <Button
            android:id="@+id/btn_single"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:onClick="@{(v)->vm.btnLogin(v)}"
            android:text="@{vm.btnText}" />

    </RelativeLayout>
</layout>
  • 完整的 自定义属性
    @BindingAdapter("imageUrl")
    fun imageUrl(view: ImageView, url: String?) {
        url?.let {
            Glide.with(view.context)
                .load(url)
                .into(view)
        }
    }
    
    @BindingAdapter("imageUri")
    fun imageUri(view: ImageView, uri: Uri?) {
        uri?.let {
            Glide.with(view.context)
                .load(uri)
                .into(view)
        }
    }
  • 千万别忘了添加插件 (后两个) 否则 BindingAdapter 会报错的
plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-android-extensions'
    id 'kotlin-kapt'
}

四 总结关键点(自定义属性)

  • 通过DataBinding 自定义属性 完成图片自动加载

五 感谢

Databinding中ImageView的用法和坑(Java和Kotlin),附带Glide用法(https://blog.csdn.net/qq_33337504/article/details/98615593)
Android DataBinding (四) 自定义属性(https://blog.csdn.net/tianjf0514/article/details/75195124)

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值