Android MVVM架构模式(二)——DataBinding框架(二)

来源:互联网 发布:ovid数据库的网址 编辑:程序博客网 时间:2024/06/05 07:14

Android MVVM架构模式(二)——DataBinding框架(二)


一 表达式
支持的表达式:
数学计算 + - / * %

字符串连接 +

逻辑 && ||

二进制 & | ^

一元运算符 + - ! ~

位移 >> >>> <<

比较 == > < >= <=

instanceof

组 ()

文字 - 字符,字符串,数字, null

类型转换

函数调用

字段存取

数组存取 []

三目运算符 ?:

如:
数组存取 []

<variable name="list" type="List<String>"> <variable name="index" type="int">android:text="@{list[index]}"

三目运算符 ?:

android:visibility="@{id>5 ? View.GONE : View.VISIBLE}"

资源引用:

@{@string/name}@{@drawable/fengjing1}

不支持的表达式:

this

super

new


二 数组使用
这里的实例是RecyclerView中的每个Item,有9张图,然后让这9张图Biding

1 创建variable

<variable        name="position"        type="int"/>    <variable        name="ninePictureArray"        type="String[][]"/>

2 ImageView中引用

app:imageUrl="@{ninePictureArray[position][0]}"app:imageUrl="@{ninePictureArray[position][1]}"...

position是第几个Item的标记,后面的数字是第几张图片

3 再用binding去set值
这里是在Adapter中

void bindItem(final int bindPosition{mItemLayoutBinding.setItemViewModel(aItemViewModel);mItemLayoutBinding.setNinePictureArray(mPicture);// 这里传入的是二维数组mItemLayoutBinding.setPosition(bindPosition);  }

传入二维数组mPicture和int的position的值(这里通过形参获取)
这样XML的二维数组ninePictureArray就有了值,再在各个ImageView中去取不同位置的值


三 DataBinding结合RecyclerView
RecyclerView使用参考:
http://blog.csdn.net/weixin_37577039/article/details/78581423

首先

MAinActivity(也就是有RecyclerView)的地方

 //改写 setContentView 进行MainActivity和activity_main的连接        ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);        //通过ID去绑定XML的组件        mRecyclerView = activityMainBinding.recyclerView;

再去ViewModel中加载数据

itemViewModel2.initData(MainActivity.this);

加载布局管理器

// 加载布局管理器        initView();private void initView() {        mLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);        //设置布局管理器        mRecyclerView.setLayoutManager(mLayoutManager);        //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能        mRecyclerView.setHasFixedSize(true);        //设置adapter        mRecyclerView.setAdapter(itemViewModel2.mAdapter);        //添加分割线        mRecyclerView.addItemDecoration(new ItemDivideLineView(                this, DividerItemDecoration.VERTICAL));    }

在Adpater中:
1 根据XML的名字编译过后的Databinding 见上方有讲解 创建对象
在onCreateViewHolder中:

 // 传入itemViewModel给MyComponent // MyComponent.getObject3(aItemViewModel); // 这里还使用了ImageView 所以传入参数给 new MyComponent()  // 若只使用RecyclerView不使用ImageView,后面的newMyComponent() 可以删掉ItemLayoutBinding itemLayoutBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.item_layout,parent, false,new MyComponent()); return new ViewHolder(itemLayoutBinding);

2 onBindViewHolder中

  // 传过来的ArrayList 根据position绑定值    position为当前界面显示的item条目  从0开始 若有多个则调用多个 但是也是一个个按先后顺序的 holder.bindItem(position);

3 在ViewHolder class中:

//声明:    ItemLayoutBinding mItemLayoutBinding;    public ViewHolder(ItemLayoutBinding itemLayoutBinding) {        super(itemLayoutBinding.itemLayout);        this.mItemLayoutBinding = itemLayoutBinding;    }    void bindItem(final int bindPosition){        // 不是创建新的itemViewModel        //ItemViewModel itemViewModel = new ItemViewModel();        aItemViewModel.setOtherPosition(bindPosition);        mItemLayoutBinding.setItemViewModel(aItemViewModel);        mItemLayoutBinding.setNinePictureArray(mPicture);        mItemLayoutBinding.setPosition(bindPosition);    }}

四 DataBinding使用ImageView加载网络图片(这里是RecyclerView中的ImageView)
XML中:

// valiable 中  <variable        name="user"        type="包名.User类(Bean类)"/>//ImageView中app:imageUrl="@{ user.UserImage}"

会调用方法getUserImage()
java中:

 public URL getUserImage() throws MalformedURLException {        URL url = new URL(String类型的url);        return url;    }

但是会出现一个问题,就是不识别app:的属性
app:imageUrl=”@{ user.UserImage}”里的user.UserImage为绿色不是白色
原因,这个app:imageUrl是自定义的XML方法,不是系统自带的,因此需要自定义方法设置
解决:
1

@BindingAdapter("app:imageUrl")// 这里的函数名没有约束 编译时会根据上面的@注解进行绑定 public void loadImageForUrl(ImageView imageView, URL url) {    }//也可以绑定多个    @BindingAdapter({"app:imageUrl","error"})    public void loadImageForUrl(ImageView imageView, String url, Drawable error) {        Log.i("setImageUrl", String.valueOf(url));        Log.d("setImageUrl", "setImageUrl is Called");          //Glide的使用    }//XML中app:imageUrl="@{itemViewModel.UserImage}"app:error="@{@drawable/fengjing1}"

原理是:
通过@注解,设置自定义的xml的方法,app:imageUrl的组件去调用这个方法 传入这个组件(如imageView) 所以不需要findID 再传入方法中的值,(可以是常量,也可以是databinding的变量)


运行后会报错:

 java.lang.IllegalStateException: Required DataBindingComponent is null in class ItemLayoutBinding. A BindingAdapter in com.scnu.sihao.sinaweibodemo.ViewModel.ItemViewModel is not static and requires an object to use, retrieved from the DataBindingComponent. If you don't use an inflation method taking a DataBindingComponent, use DataBindingUtil.setDefaultComponent or make all BindingAdapter methods static.                                                                               at android.databinding.ViewDataBinding.ensureBindingComponentIsNotNull(ViewDataBinding.java:554)

2 创建类implements DataBindingComponent

public class MyComponent implements android.databinding.DataBindingComponent{   private static ItemViewModel myItemViewModel;    @Override    public ItemViewModel getItemViewModel() {        return myItemViewModel;    }    public static void getObject3(ItemViewModel itemViewModel){        myItemViewModel=itemViewModel;    }}

3 在使用了app:imageUrl的xml对应的Activity或者Adapter中
这里是Adapter

//通过DataBindingUtil加载我们的布局文件//在这里我们实例化了一个我们定义的DataBindingComponent对象MyComponent//这个是非常关键的一个地方,否则系统会使用DataBindingUtil#getDefaultComponent()拿到的默认实例作为参数        //如果我们在此之前没有调用DataBindingUtil.setDefaultComponent()方法,上面的方法就会返回nullItemLayoutBinding itemLayoutBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.item_layout,                parent, false,new MyComponent());

Activity中也是一样

ActivityMainBinding activityBinding = DataBindingUtil.setContentView(this, R.layout.activity_main,new MyComponent());

报错:Error:(220, 17) 警告: Application namespace for attribute app:imageUrl will be ignored.

解决:
将@BindingAdapter的(app:) app去掉


五 做完了这些,还是发现图片加载不出来,因为图片的加载不能在主线程中进行,这里使用Glide缓存库进行加载缓存:

databinding+Glide图片缓存库使用参考:
http://blog.csdn.net/weixin_37577039/article/details/78698865


RecyclerView+ImageView+Databinding结合使用参考项目:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
https://github.com/5ingwings/SinaWeiBoDemo


**还有高级的如:
Dynamic Variables
Attribute setters
转换器 (Converters)
动画
mooc的高级篇**


阅读全文
0 0
原创粉丝点击