前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android数据绑定技术二,企业级开发

Android数据绑定技术二,企业级开发

作者头像
cMusketeer
发布2018-03-28 11:00:08
7490
发布2018-03-28 11:00:08
举报
文章被收录于专栏:Android机器圈Android机器圈

PS:上一篇文章写了Databinding的简单使用,写了一个绑定textview的示例,和绑定的一些用法,估计有的人会说,之前的写的好好的,为什么要数据绑定这样的写法呢,没办法,社会在进步,当然是怎么好怎么做了。这篇主要是内容是

  • 数据绑定加载网络图片
  • 数据绑定ListView
    •   自定义适配器(数据绑定通用适配器)
    • item中某一个控件点击事件并刷新定位

先说一下数据绑定加载网络图片和本地图片,图片的载体我们都知道用ImageView,但是如果直接把图片通过set的形式传给xml文件的话,数据绑定是无法直接解析到的,这就用到了自定义属性,我们来实现一下。这次的代码先按照之前的接着写。

1:先加载一个图片处理的库,Glide

代码语言:javascript
复制
  compile "com.github.bumptech.glide:glide:3.7.0"

 2:在user_layout.xml文件中用

注意:app:imageUrl,此处的imageUrl是工具类的注解,只要不过分,可以随便写,但要记住,我们下面还要用

代码语言:javascript
复制
 <ImageView
            android:layout_width="100dp"
            android:layout_height="100dp"
            app:imageUrl="@{ user.icon }"/>

 3:我们写一个工具类ImgUtils.java,专门来处理图片

代码语言:javascript
复制
@BindingAdapter({"imageUrl"})这里的imageUrl就是上面所写的app:imageUrl。这里的static可是有含义的,如果没有static的话,那就是必须用DatabindingComponent来创建对象并返回,不过加上static就可以了,这个有兴趣可以去搜一下。
代码语言:javascript
复制
public class ImgUtils {
    @BindingAdapter({"imageUrl"})
    public static void  loadImage(ImageView imageView,String imgUrl){
        if(imgUrl  == null){
            imageView.setImageResource(R.mipmap.ic_launcher);
        }
        else{
            Glide.with(imageView.getContext()).load(imgUrl).into(imageView);
        }

    }
}

4:最后activity处理代码

代码语言:javascript
复制
DatabindingBinding databindingBinding=DataBindingUtil.setContentView(this, R.layout.databinding);
        Users users=new Users();
        users.setName("用户名:");
        users.setAddress("地址:");
        users.setEmail("E-mail:");
        users.setIcon("https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1513564670&di=0b7e42fd05b25e0511c016a1b6bdd7fc&src=http://pic29.photophoto.cn/20131211/0005018385835470_b.jpg");
        users.setVip(true);

        Users users1=new Users();
        users1.setName("李四");
        users1.setAddress("北京");
        users1.setEmail("1245334@163.com");
//        users1.setIcon();
        users1.setVip(true);
        List<Users> list=new ArrayList<>();
        list.add(users);
        list.add(users1);
        databindingBinding.setUsers(list);

 这样子就可以实现了,上面的代码和我上一篇写的有关,如果不看第一篇的话,可能会看不懂。

左边是网络加载,右边是本地加载

好,到这里,加载网络图片就已经做好了,下面我们实现一个数据绑定listview,还是老样子,搞清楚几个步骤

  • 创建自定义Adapter(通用)
  • 并且获取上面的某一个控件的点击事件,刷新定位
  • 如何把通用适配器和listview关联,并且数据也能被加载。

1:创建 自定义CommonAdapter.java(通用)

我老是说通用,怎么才能通用呢,其实很简单,只要把layoutID,variableID等通过传参的形式传入即可。我们之前都会用到Viewholder,在这里就不需要了,关键还是viewDataBinding = DataBindingUtil.inflate(LayoutInflater.from(context), layoutId, parent, false);代码很少。也很简单。 return viewDataBinding.getRoot();中getRoot(),底层代码就是返回一个view。

代码语言:javascript
复制
package databindinglistview;

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

import java.util.List;

/**
 * Created by cMusketeer on 17/12/18.
 *
 * @author cmusketeer
 */
public class CommonAdapter<T> extends BaseAdapter {

    public Context context;
    public List<T> list;//不确定传过来的值泛型
    public int layoutId;//布局ID
    public int variableId;//变量ID

    public CommonAdapter(Context context, int layoutId, List<T> list, int variableId) {
        this.context = context;
        this.layoutId = layoutId;
        this.list = list;
        this.variableId = variableId;
    }

    @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 viewDataBinding = null;
        if (convertView == null){
            viewDataBinding = DataBindingUtil.inflate(LayoutInflater.from(context), layoutId, parent, false);
        }else {
            viewDataBinding = DataBindingUtil.getBinding(convertView);
        }
        viewDataBinding.setVariable(variableId,list.get(position));


        return viewDataBinding.getRoot();
    }
}

 2:布局文件dblistview.xml

关键:

代码语言:javascript
复制
    <data>

        <variable
            name="adapter1"
            type="android.widget.BaseAdapter"></variable>
    </data>

这个地方只能这样写,有的人到这一步可能会有疑问,为什么不是把CommonAdapter加载进来呢,别急,自定义Adapter是在Activity中被加载。

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <data>

        <variable
            name="adapter1"
            type="android.widget.BaseAdapter"></variable>
    </data>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:adapter="@{adapter1 }"
        ></ListView>

</LinearLayout>
</layout>

 写到这还要写一个item,毕竟listview的样式是不能少的嘛;这里才是真正赋值的地方,注意:databinding.Users,为路径,你我可能写的路径不一样。

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <data>
        <variable
            name="user"
            type="databinding.Users"></variable>

    </data>
<LinearLayout
    android:layout_width="match_parent"
    android:orientation="horizontal"
    android:layout_height="match_parent">
    <ImageView
        android:layout_width="100dp"
        android:layout_height="80dp"
        app:imageUrl="@{ user.icon }"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:orientation="vertical">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:textSize="25dp"
            android:onClick="@{user.click1}"
            android:text="@{user.name}"/>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="30dp"
            android:textColor="#c4c3c3"
            android:text="@{user.address}"/>

    </LinearLayout>

</LinearLayout>
</layout>

 Users.java  

代码语言:javascript
复制
package databinding;

import android.view.View;
import android.widget.Toast;

public class Users {

    public  String name,address,email;
    private boolean vip;
    public String icon;

    public String getIcon() {
        return icon;
    }

    public void setIcon(String icon) {
        this.icon = icon;
    }

    public boolean isVip() {
        return vip;
    }

    public void setVip(boolean vip) {
        this.vip = vip;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getName() {
        return name;
    }

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

    public void click1(View view){
        Toast.makeText(view.getContext(), "点击了:"+name, Toast.LENGTH_SHORT).show();
    }
    public boolean longClick1(View view){
        Toast.makeText(view.getContext(), "长按了:"+name, Toast.LENGTH_SHORT).show();
        return true;
    }
}

 ImgUtils上面写过了,翻一翻即可

3:ListviewActivity.java

这里面写一个值和加载适配器,值是模拟的,但图片是真的,是从网上下载的,需要联网。需要注意的是retrofit.cn.myretrofit.BR.user,这个就是variableID,在我们的控件生成一个R文件的时候,它也会生成一个BR文件,里面都是int,你懂的。

代码语言:javascript
复制
public class ListviewActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DblistviewBinding dblistviewBinding=DataBindingUtil.setContentView(this, R.layout.dblistview);
        List<Users> list=new ArrayList<>();
        for(int i=0;i<50;i++){
            Users users=new Users();
            users.setIcon("https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1513564670&di=0b7e42fd05b25e0511c016a1b6bdd7fc&src=http://pic29.photophoto.cn/20131211/0005018385835470_b.jpg");
            users.setName("图片   :"+i);
            users.setAddress("北京");
            list.add(users);
        }

        CommonAdapter<Users> commonAdapter=new CommonAdapter<Users>(this,R.layout.item_listview,list, retrofit.cn.myretrofit.BR.user);

        dblistviewBinding.setAdapter1(commonAdapter);

    }
}

这里的是给局部加的监听,所以点击(字)图片:0等才有反应,点击北京和image是没有反应的。

 完:

4:item中某一个控件点击事件并刷新 

1:我们在使用普通的listview处理方法的时候,点击item中某一个控件,写的逻辑很多,还要通过接口等刷新,而且如果处理不好的话刷新后一般还会跳到第一条数据。在这数据绑定统统只用几行代码搞定。

对于商品购买添加什么的非常好用

代码语言:javascript
复制
package databinding;

import android.databinding.BaseObservable;
import android.databinding.Bindable;
import android.view.View;
import android.widget.Toast;

import retrofit.cn.myretrofit.BR;

public class Users extends BaseObservable {

    public  String name,address,email;
    private boolean vip;
    public String icon;

    public String getIcon() {
        return icon;
    }

    public void setIcon(String icon) {
        this.icon = icon;
    }

    public boolean isVip() {
        return vip;
    }

    public void setVip(boolean vip) {
        this.vip = vip;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

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

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

    public void click1(View view){
        Toast.makeText(view.getContext(), "点击了:"+name, Toast.LENGTH_SHORT).show();
    }
    public boolean longClick1(View view){
        Toast.makeText(view.getContext(), "长按了:"+name, Toast.LENGTH_SHORT).show();
        return true;
    }

    public void click2(View view){
        setName("我被点击了");
    }
}

这里代码我做了修改,extends BaseObservable 观察者(可以时刻观察某个东西的变化),可以看到 getName方法上加了一个注解,@Bindable,在setName中notifyPropertyChanged(BR.name);这里需要一个id只对name做个监听,所以只能点击name才有变化,而且点击后会只刷新单个item,也可以刷新整个,但在没必要的情况下刷新整个listview是好资源的。方法_all就是对全部进行刷新。

使用click2()方法和之前一样android:onClick="@{user.click2}"。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-12-18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1:先加载一个图片处理的库,Glide
  •  2:在user_layout.xml文件中用
  •  3:我们写一个工具类ImgUtils.java,专门来处理图片
  • 1:创建 自定义CommonAdapter.java(通用)
  •  2:布局文件dblistview.xml
  • 3:ListviewActivity.java
  • 4:item中某一个控件点击事件并刷新 
相关产品与服务
图片处理
图片处理(Image Processing,IP)是由腾讯云数据万象提供的丰富的图片处理服务,广泛应用于腾讯内部各产品。支持对腾讯云对象存储 COS 或第三方源的图片进行处理,提供基础处理能力(图片裁剪、转格式、缩放、打水印等)、图片瘦身能力(Guetzli 压缩、AVIF 转码压缩)、盲水印版权保护能力,同时支持先进的图像 AI 功能(图像增强、图像标签、图像评分、图像修复、商品抠图等),满足多种业务场景下的图片处理需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档