Android databinding详解(二)--activity解析

本文详细讲解了在集成Data Binding框架后,Activity中的编写方式。介绍ActivityMainBinding类的生成规则及其作用,如何替代setContentView(),以及如何实现Activity与布局的交互。通过示例展示了数据变化如何实时更新界面,同时预告了Data Binding的其他应用场景,如自定义属性、自定义控件等。

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

        在上篇Android databinding详解(一)–layout解析中我们学习了data binding在layout中的结构和语法,如果没看过的话,最好看一遍,两个章节是相互关联的,在本篇文章中主要讲述的是集成了data binding框架以后,我们的Activity文件中应该如何书写?下面依旧是先粘贴上Activity所有的代码, 然后通过代码讲述它与普通的Activity的不同之处。

MainActivity

package wshuttle.com.testmvvm.ui;

import android.databinding.DataBindingUtil;
import android.databinding.ObservableBoolean;
import android.databinding.ObservableInt;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.ListView;
import android.widget.Toast;

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

import wshuttle.com.testmvvm.BR;
import wshuttle.com.testmvvm.R;
import wshuttle.com.testmvvm.adapter.BaseListViewAdapter;
import wshuttle.com.testmvvm.adapter.BaseRecycleViewAdapter;
import wshuttle.com.testmvvm.bean.OrderInfo;
import wshuttle.com.testmvvm.bean.UserInfo;
import wshuttle.com.testmvvm.databinding.ActivityMainBinding;

/**
 * MVVM:@{},@={},data import variable Event(事件返回值相同即可)
 */
public class MainActivity extends BaseActivity {
    public ObservableBoolean show = new ObservableBoolean();
    public ObservableInt imageUrl = new ObservableInt(R.mipmap.ic_launcher);
    private OrderInfo orderInfo;
    ActivityMainBinding bing;
    BaseRecycleViewAdapter adapter;
    ListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        bing = DataBindingUtil.setContentView(this, R.layout.activity_main);
        Toolbar toolbar = bing.toolbar;
        setSupportActionBar(toolbar);
        toolbar.setTitle("ToolBar");
        toolbar.setTitle("Use");

        orderInfo = new OrderInfo("20160922142752", "曹操");
        bing.notifyPropertyChanged(BR.imageUrl);
        show.set(true);
        bing.setShow(show);
        bing.setUserInfo(new UserInfo());
        bing.setMyEventHandler(new MyEventHandler());
        bing.setOrderInfo(orderInfo);
        bing.setImageUrl(imageUrl);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                 orderInfo.setOrderid("ABCDEFGHIJK");
                 orderInfo.setRescueName("刘备");
               //  adapter.addItem(new UserInfo(6,"关羽","admin"));
                 show.set(false);
                imageUrl.set(R.drawable.big6);
            }
        }, 3000);

        listView = bing.listView;
        // initRecyclerView();
        initListView();
    }

    Handler handler = new Handler(){};
    List<UserInfo> lists;

    private void initListView() {
        lists = new ArrayList<>();
        UserInfo userInfo1 = new UserInfo(R.string.app_name, "admin", "admin");
        UserInfo userInfo2 = new UserInfo(R.string.app_name, "张三", "user");
        UserInfo userInfo3 = new UserInfo(R.string.app_name, "李四", "user");
        UserInfo userInfo4 = new UserInfo(R.string.app_name, "王五", "user");
        lists.add(userInfo1);
        lists.add(userInfo2);
        lists.add(userInfo3);
        lists.add(userInfo4);
        BaseListViewAdapter listAdapter = new BaseListViewAdapter(lists, R.layout.layout_user_item, BR.userInfo);
        listView.setAdapter(listAdapter);
    }

//    private void initRecyclerView() {
//        bing.recyclerView.setHasFixedSize(true);                           //用来使RecyclerView保持固定的大小,该信息被用于自身的优化。
//        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
//        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
//        bing.recyclerView.setLayoutManager(linearLayoutManager);//设置布局管理器,决定视图放在画面的哪个位置
//        bing.recyclerView.setItemAnimator(new DefaultItemAnimator());//设置Item变化的动画
////        bing.recyclerView.addItemDecoration();    //添加分割线
//        lists = new ArrayList<>();
//        UserInfo userInfo1 = new UserInfo(1,"admin","admin");
//        UserInfo userInfo2= new UserInfo(2,"张三","user");
//        UserInfo userInfo3= new UserInfo(3,"李四","user");
//        UserInfo userInfo4= new UserInfo(4,"王五","user");
//        lists.add(userInfo1);
//        lists.add(userInfo2);
//        lists.add(userInfo3);
//        lists.add(userInfo4);
//        adapter = new BaseRecycleViewAdapter(lists,R.layout.layout_user_item,BR.userInfo);
//        adapter.setListener(new BaseRecycleViewAdapter.OnItemClickListener() {
//            @Override
//            public void onItemClick(ViewDataBinding dataBinding, int position) {
//            }
//        });
//        bing.recyclerView.setAdapter(adapter);
//    }


    /**
     * 自定义事件Handler
     */
    public class MyEventHandler {
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.btnGetType: {
                    Toast.makeText(MainActivity.this, orderInfo.getRescueName(), Toast.LENGTH_SHORT).show();
                    break;
                }
            }
        }

        public void getUser(UserInfo userInfo) {
            Toast.makeText(MainActivity.this,"id:" + userInfo.id.get() + ",name:" + userInfo.name.get() + ",type:" +userInfo.type.get() ,Toast.LENGTH_SHORT).show();
        }
    }
}

一、Binding
        在MainActivity我们先不看别的,我们看见了一个ActivityMainBinding的类,看这个类名就大概能猜到这个类是与data binding框架相关的,但是究竟是何种关系呢?实际上呢,ActivityMainBinding就是根据layout文件编译生成的,也就相当于一个layout转化的一个Java类,下面我们来看看它的转换规则。
        首先我们看看它的命名规则,这个我们新建以后自动生成的layout文件叫做activity_main.xml,而我们自动生成的Binding类叫ActivityMainBinding,生成的规则是以下划线作为分割线,首字母变成大写,以Binding结尾,Binding类的存放是在app\build\generated\source\apt\debug\com\wshuttle\trailerplatform\databinding的路径下的
        我们再看看Binding类内部的生成规则。Binding类会对在layout中data节点下定义的变量都生成一个私有的变量值,并为它生成get和set的方法,方便我们直接对变量进行赋值;会对layout中有id的控件生成一个public的变量,可如同代码中bing.listView获取layout的listview,并且控件的类型获取时已经确定了, 不再需要强制转换等任何的操作。

以下是Binding类生成的变量

    private static final android.databinding.ViewDataBinding.IncludedLayouts sIncludes;
    private static final android.util.SparseIntArray sViewsWithIds;
    static {
        sIncludes = null;
        sViewsWithIds = new android.util.SparseIntArray();
        sViewsWithIds.put(R.id.toolbar, 10);
        sViewsWithIds.put(R.id.listView, 11);
    }
    // views
    public final android.widget.Button btnGetName;
    public final android.widget.Button btnGetType;
    public final android.widget.ListView listView;
    private final android.widget.LinearLayout mboundView0;
    private final android.widget.EditText mboundView1;
    private final android.widget.EditText mboundView3;
    private final android.widget.TextView mboundView6;
    private final android.widget.TextView mboundView7;
    private final com.facebook.drawee.view.SimpleDraweeView mboundView8;
    private final android.widget.ImageView mboundView9;
    public final android.support.v7.widget.Toolbar toolbar;
    public final android.widget.EditText username;
    // variables
    private wshuttle.com.testmvvm.bean.OrderInfo mOrderInfo;
    private android.databinding.ObservableInt mImageUrl;
    private wshuttle.com.testmvvm.bean.UserInfo mUserInfo;
    private android.databinding.ObservableBoolean mShow;
    private wshuttle.com.testmvvm.ui.MainActivity.MyEventHandler mMyEventHandler;
    private final android.view.View.OnClickListener mCallback1;
    // values
    // listeners
    private OnClickListenerImpl mAndroidViewViewOnCl;

        现在看来是不是好像有点感觉了?我们直接bing.get或.就可以直接获取layout中绑定的变量以及界面上的控件,我们根本无需再使用注解框架去对界面上的控件进行获取,直接.就可以获取到,是不是很方便啦, 而且再也不担心什么ClassCast失败了,因为你.的时候已经帮你确定了你获取的什么控件。注意:data binding在实际的开发过程中,由于要根据你敲写的代码然后再生成Binding类,有时候你在layout已经书写完了的id或者变量可能在Activity会出现错误,但是没关系,如果你直接运行的话没错误的话就可以了,或者尝试rebuild project(本人觉得比较耗时)

二、activity的setContentView
        在以上代码上我们是不是没看见setContentView(R.layout.activity_main);但是我们可以发现代码中有一句

bing = DataBindingUtil.setContentView(this, R.layout.activity_main);

这句话实际上与setContentView(R.layout.activity_main);是相同的。注意的是DataBindingUtil是data binding中的一个工具类,可以用于进行设置activity、获取layout等的操作,它的setContextView的方法第一个参数就是你要展示的activity对象、第二个参数就是layoutid啦。

三、activity与layout的交互
        以上介绍了Binding的生成规则、setContextView,下面就是重点–activity与layout的交互。看代码中我们定义了一下字段与界面上定义的变量进行一一对应

public ObservableBoolean show = new ObservableBoolean();
public ObservableInt imageUrl = new ObservableInt(R.mipmap.ic_launcher);
private OrderInfo orderInfo;

,之前在上一篇Android databinding详解(一)–layout解析我们定义的这些了变量,在activity我们定义以上三个字段与之形成对应,实际上就是赋值到layout中,这样子我们改变了activity中的这几个变量就会改变layout中的变量,然后便会刷新界面(记住上节讲的要定义Observable或者执行bing.notifyPropertyChanged(BR.对应的字段))。实际上我们也可以不定义变量,但是就必须每次改变值都调用bing.set的方法,在这里我比较喜欢定义变量来处理layout的数值,看个人喜好咯。
        定义了变量以后自然就是设置到layout中了,看官请看以下代码

show.set(true);
bing.setShow(show);
bing.setUserInfo(new UserInfo());
bing.setMyEventHandler(new MyEventHandler());
bing.setOrderInfo(orderInfo);
bing.setImageUrl(imageUrl);

以上我们看见,第一句是对定义的show进行赋值,show不是简单的boolean类型,是一个ObservableBoolean它实际上是一个引用类型,所以赋值需要set进去。后面几句是我们将activity和layout的变量进行关联起来,在上一篇中我们设置的userInfo是执行了双向绑定的,其他的都是单向进行绑定的。
        以上的工作都做完了以后就是要执行我们的逻辑了,在这里我们实现的只是单击获取orderInfo的值、单击获取输入的内容、三秒更改orderInfo的信息查看界面有无改变。handler.postDelayed我们三秒后修改了orderInfo的信息的内容以及show的值,根据在layout我们设置的逻辑,orderInfo修改后,界面上展示的信息真的改变了,还有show改变后,一个imageView也消失不见了;单击获取车主姓名以后,我们可以看见提示的也是修改后的orderInfo的信息;单击获取用户信息以后,我们可以看见name,type的值都提示输入的信息,但是由于id没有执行双向绑定维持的是默认值0。

四、总结
        看起来是不是很神奇,在layout执行了一部分逻辑,在Activity中绑定变量,直接获取控件等等。实际上data binding还有很多其他的好处,比如说自定义属性,其实在文章中我们并没有解释如何绑定imageview,其实绑定imageview我们使用的就是自定义的属性,这个将在下一篇文章中进行解析,实现透露这个方法叫做bindAdapter,等等。
        到现在为止我们已经知道了data binding的基本原理以及一系列的操作,今后的章节将会补充一些其他方面的知识,bindAdapter(自定义属性)、自定义控件(更简单)、与RecyclerView的结合使用、一系列基类的定义等等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值