MVVM + dataBinding

本文详细介绍MVVM模式结合DataBinding技术的应用实例,包括简单的文本绑定、图片加载更新及ListView的绑定实现。

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

MVVM + dataBinding

mvvm模式不做过多讲解,参考下面文章或其他文章对mvvm描述
http://www.jianshu.com/p/6872b699879d

后面又发现一篇比较好的文章,补上
http://lib.youkuaiyun.com/article/android/57804?knId=295

引入 dataBinding

按网上部分文章的引入方式,会报如下错误

Error:(2, 1) A problem occurred evaluating project ':mvvm'.
> org/apache/commons/lang3/StringUtils

解决办法(基本现在as都是比较高的了,不够高自行升级下)
这里写图片描述
直接就可以引用了

简单示例1

1.布局

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="stu"
            type="com.wuhai.mvvm.Student" />
    </data>
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{stu.name}"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{stu.addr}"/>
    </LinearLayout>
</layout>

2.model

package com.wuhai.mvvm;

/**
 * Created by wuhai on 2017/08/14 15:47.
 * 描述:
 */

public class Student {

    private String name;
    private String addr;

    public Student(String name, String addr) {
        this.name = name;
        this.addr = addr;
    }

    public String getName() {
        return name;
    }

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

    public String getAddr() {
        return addr;
    }

    public void setAddr(String addr) {
        this.addr = addr;
    }
}

3.绑定view

package com.wuhai.mvvm;

import android.databinding.DataBindingUtil;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.wuhai.mvvm.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_main);
        ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        binding.setStu(new Student("路飞","海贼王"));//model和布局绑定
    }
}

※ActivityMainBinding这个类是根据布局生成的

运行效果
这里写图片描述

简单示例2
a.传统findViewById +dataBinding
b.imageview绑定
c.修改Model后自动更新UI
1.布局 变化

<?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>
        <variable
            name="stu"
            type="com.wuhai.mvvm.Student" />
    </data>
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{stu.name}"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{stu.addr}"/>
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:photo="@{stu.photo}"/>
        <Button
            android:id="@+id/btn01"
            android:text="更新信息"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <EditText
            android:id="@+id/name"
            android:layout_width="100dp"
            android:layout_height="wrap_content" />
        <EditText
            android:id="@+id/addr"
            android:layout_width="100dp"
            android:layout_height="wrap_content" />
    </LinearLayout>
</layout>

a.可以给控件增加id
b.图片要使用自定义属性
2.model

package com.wuhai.mvvm;

import android.databinding.BaseObservable;
import android.databinding.Bindable;
import android.databinding.BindingAdapter;
import android.util.Log;
import android.widget.ImageView;

import com.squareup.picasso.Picasso;

/**
 * Created by wuhai on 2017/08/14 15:47.
 * 描述:
 */

public class Student extends BaseObservable{

    private String name;
    private String addr;
    private String photo;

    public Student(String name, String addr) {
        this.name = name;
        this.addr = addr;
    }

    public Student(String name, String addr, String photo) {
        this(name,addr);
        this.photo = photo;
    }

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

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

    @Bindable
    public String getAddr() {
        return addr;
    }

    public void setAddr(String addr) {
        this.addr = addr;
        notifyPropertyChanged(BR.addr);
    }

    public String getPhoto() {
        return photo;
    }

    public void setPhoto(String photo) {
        this.photo = photo;
    }

    @BindingAdapter("photo")
    public static void getInternetImage(ImageView iv, String url) {
        Picasso.with(iv.getContext()).
                load(url).
                error(R.mipmap.weixin).
                into(iv);
    }
}

b.@BindingAdapter(“photo”)对于图片加载使用注解
实现静态方法getInternetImage,在生成的ActivityMainBinding里你可以查到关联的iv、并且将来加载的url其实就是getPhoto()返回值
※这里注意一定要加网络权限,毕加索并不会主动告诉你缺少权限的,我都被自己蠢到了
c.类继承BaseObservable,并且name、addr的get方法加上@Bindable注解,set方法实现notifyPropertyChanged(BR.name);
这里新加注解的话记得rebuild一下BR后属性才有
3.绑定view

package com.wuhai.mvvm;

import android.databinding.DataBindingUtil;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import com.squareup.picasso.Picasso;
import com.wuhai.mvvm.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn01;
    private EditText name;
    private EditText addr;
    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_main);
        binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        binding.setStu(new Student("路飞","海贼王","https://www.baidu.com/img/bd_logo1.png"));//model和布局绑定

        //取布局id 方式1
//        View view = binding.getRoot();
//        btn01 = (Button) view.findViewById(R.id.btn01);
//        name = (EditText) view.findViewById(R.id.name);
//        addr = (EditText) view.findViewById(R.id.addr);

        //取布局id 方式2
        btn01 = binding.btn01;
        name = binding.name;
        addr = binding.addr;

        btn01.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn01:
                String nameStr = name.getText().toString().trim();
                String addrStr = addr.getText().toString().trim();

                //示例 不做效果展示了,这里只是重新绑定model而已
//                binding.setStu(new Student(nameStr,addrStr));

                //示例2
                Student student = binding.getStu();
                student.setName(nameStr);
                student.setAddr(addrStr);
                break;
        }
    }
}

a.binding.getRoot()取得rootview,然后通过findViewById查找控件,后来发现其实有更简单的方法,就是直接binding.控件id
b.图片展示跟之前name、addr一样,绑定model即可
c.我们点击”更新信息”,改变绑定model同时UI也随着变化
运行效果
这里写图片描述

简单示例3
绑定listview
1.布局
activity_list.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

</RelativeLayout>

item_student.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>
        <variable
            name="stu"
            type="com.wuhai.mvvm.Student"/>
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="96dp"
        >

        <ImageView
            android:id="@+id/iv"
            android:layout_width="96dp"
            android:layout_height="96dp"
            android:padding="6dp"
            app:photo="@{stu.photo}"/>

        <TextView
            android:id="@+id/description"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="8dp"
            android:layout_toRightOf="@id/iv"
            android:ellipsize="end"
            android:maxLines="3"
            android:text="@{stu.name}"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="8dp"
            android:layout_toRightOf="@id/iv"
            android:layout_alignParentBottom="true"
            android:layout_marginBottom="2dp"
            android:text="@{stu.addr}"
            android:textStyle="bold"/>
    </RelativeLayout>

</layout>

布局只绑定item对应的即可,没啥可讲的
2.model 我们使用上面的Student类
3.绑定实现
ListActivity

package com.wuhai.mvvm;

import android.content.Context;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;

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

public class ListActivity extends AppCompatActivity {

    private ListView mListView;
    private StudentAdapter mAdapter;

    public static void startActivity(Context context) {
        Intent intent = new Intent(context, ListActivity.class);
        context.startActivity(intent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list);

        mListView = (ListView) findViewById(R.id.listview);
        mAdapter = new StudentAdapter(this);
        mListView.setAdapter(mAdapter);
        initData();
    }

    private void initData() {
        List<Student> datas = new ArrayList<>();
        for(int x=0;x<20;x++){
            Student student = new Student();
            student.setAddr("地址"+x);
            student.setName("名字"+x);
            student.setPhoto("http://www.lecuntao.com/homenew/templates/default/images/hi.jpg?v=09e9caa5d6");
            datas.add(student);
        }
        mAdapter.setData(datas);
    }
}

StudentAdapter
我们这里着重看下adapter类,其基类不贴出来了,有兴趣的话直接在最后的git下载来看

package com.wuhai.mvvm;

import android.content.Context;
import android.databinding.DataBindingUtil;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.wuhai.mvvm.databinding.ItemStudentBinding;

/**
 * Created by wuhai on 2017/08/15 17:40.
 * 描述:
 */

public class StudentAdapter extends BaseDataAdapter<Student>{

    private LayoutInflater inflater;

    public StudentAdapter(Context context) {
        super(context);
        inflater = LayoutInflater.from(context);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ItemStudentBinding dataBinding;
        if (convertView == null) {
            dataBinding = DataBindingUtil.inflate(inflater, R.layout.item_student, parent, false);
        } else {
            dataBinding = DataBindingUtil.getBinding(convertView);
        }
        dataBinding.setStu(mData.get(position));

        return  dataBinding.getRoot();
    }

}

代码看上去也极其简单
a.ItemStudentBinding根据布局item_student.xml命名生成的binding类;
b.新增DataBindingUtil类,实现convertView的创建和复用;c.dataBinding.setStu(mData.get(position));实现数据UI绑定
运行效果
这里写图片描述

附上github地址(里面东西比较杂,取mvvm这个module即可)
https://github.com/oceanhai/MyFrame.git

待续…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值