乐趣区

关于android:Jetpack架构组件库介绍与基本用法

原文连贯:https://mp.weixin.qq.com/s/V2haCRugRYCGDZrA9iw7bQ

前言

== 本次次要解说的内容:==

1、Jetpack 介绍

2、Jetpack 架构组件库的相干用法

一、Jetpack 介绍

1、什么是 Jetpack

Google 官网解释:

Jetpack 是一个由多个库组成的套件,可帮忙开发者遵循最佳做法,缩小样板代码并编写可在各种 Android 版本和设施中统一运行的代码,让开发者精力集中编写重要的代码。

Jetpack 是 Google 为解决 Android 开发碎片化,打造成熟衰弱生态圈提出的战略规划,是 Google 对 Android 将来提出的倒退方向,同时它也是泛滥优良 ++Android 组件的汇合 ++。

2、为何应用 Android Jetpack

Google 官网解释:

  • 遵循最佳做法:Android Jetpack 组件采纳最新的设计办法构建,具备向后兼容性,能够缩小解体和内存泄露。
  • 打消样板代码:Android Jetpack 能够治理各种繁琐的 Activity(如后台任务、导航和生命周期治理),以便您能够专一于打造杰出的利用。
  • 缩小不统一:这些库可在各种 Android 版本和设施中以统一的形式运作,助您升高复杂性。

Jetpack 的劣势:

  • [] Jetpack 领有基于生命周期感知的能力,能够缩小 NPE(空指针异样) 解体、内存透露,为开发出强壮且晦涩的程序提供强力保障;
  • [] Jetpack 能够打消大量反复样板式的代码,能够减速 Android 的开发过程,组件可搭配工作,也可独自应用,同时配合 Kotlin 语言个性可能显著进步工作效率;
  • [] 对立开发模式,摈弃传统的 MVC, MVP;

3、JetPack 的形成

如上图:Jetpack 次要包含 4 个局部,别离是【Architecture:架构】、【UI:界面】、【behavior:行为】和【foundation:根底】。

Architecture,架构组件

目标:帮忙开发者设计持重、可测试且易保护的利用;

  1. Lifecycle:具备宿主生命周期感知能力的组件

个性:持有组件 (如 Activity 或 Fragment) 生命周期状态的信息,并且容许其余对象察看此状态;

  1. LiveData:新一代具备生命周期感知能力的数据订阅、散发组件

个性:反对共享资源、反对黏性事件的散发、不再须要手动解决生命周期、确保界面合乎数据状态;

  1. ViewModel:具备生命周期感知能力的数据存储组件

个性:页面因配置变更导致的重启,此时数据不失落;能够实现跨页面 (跨 Activity) 的数据共享;

  1. SavedState 架构组件原理解析

个性:因内存不足,电量有余导致页面被回收时能够搭配 ViewModel 实现数据存储与复原;

  1. Room:轻量级 orm 数据库,实质上是一个 SQLite 形象层

个性:应用简略(相似于 Retrofit 库),通过注解的形式实现相干性能,编译时主动生成相干实现类

  1. DataBinding:只是一种工具,解决的是 View 和数据之间的双向绑定

个性:反对数据与视图双向绑定、数据绑定空平安、缩小模板代码、开释 Activity/Fragment 压力;

  1. Paging: 列表分页组件,能够轻松实现分页预加载以达到有限滑动的成果

个性:奇妙交融 LiveData、提供多种数据源加载形式;
不足之处:不反对列表数据增删改,列表增加 HeaderView,FooterView 定位不精确;

  1. Navigation 组件原理剖析:端内对立路由组件

个性:可能为 Activity,Fragment,Dialog,FloatWindow 提供对立的路由导航服务,能够传递参数,指定导航动画,还反对深度链接等次要能力;
有余:非常依赖 xml 配置文件不利于组件化,模块化

  1. WorkManager:新一代后台任务治理组件,service 能做的事件它都能做

个性:反对周期性任务调度、链式任务调度、丰盛的工作约束条件、程序即使退出,仍旧能保障工作的执行;

Foundationy,根底组件

目标:提供横向性能,例如向后兼容性、测试、平安、Kotlin 语言反对,并包含多个平台开发的组件;

  1. Android KTX:优化了供 Kotlin 应用的 Jetpack 和 Android 平台 API,帮忙开发者以更简洁、更愉悦、更习用的形式应用 Kotlin 进行 Android 开发;
  2. AppCompat:帮忙较低版本的 Android 零碎进行兼容;
  3. Auto:开发 Android Auto 利用的组件,提供了实用于所有车辆的标准化界面和用户交互;
  4. 检测:从 AndroidStudio 中疾速检测基于 Kotlin 或 Java 的代码;
  5. 多 Dex 解决:为具备多个 Dex 文件利用提供反对;
  6. 平安:平安的读写加密文件和共享偏好设置;
  7. 测试:用于单元和运行时界面测试的 Android 测试框架;
  8. TV:构建可让用户在大屏幕上体验沉迷式内容的利用;
  9. Wear OS:开发 Wear 利用的组件;
Behavior,行为组件

目标:帮忙开发者的利用与规范 Android 服务 (如告诉、权限、分享) 相集成;

  1. CameraX:帮忙开发简化相机利用的开发工作,提供统一且易于应用的界面,实用于大多数 Android 设施,并可向后兼容至 Android 5.0(API 21);
  2. DownloadManager:解决长时间运行的 HTTP 下载的零碎服务;
  3. 媒体和播放:用于媒体播放和路由 (包含 Google Cast) 的向后兼容 API;
  4. 告诉:提供向后兼容的告诉 API,反对 Wear 和 Auto;
  5. 权限:用于检查和申请利用权限的兼容性 API;
  6. 设置:创立交互式设置,倡议应用 AndroidX Preference Library 库将用户可配置设置集成到利用中;
  7. 分享操作:能够更轻松地实现敌对的用户分享操作;
  8. 切片:切片是一种 UI 模板,创立可在利用内部显示利用数据的灵便界面元素;
UI,界面组件
  1. Animation and Transition:该框架蕴含用于常见成果的内置动画,并容许开发者创立自定义动画和生命周期回调;
  2. Emoji Compatibility:即使用户没有更新 Android 零碎也能够获取最新的表情符号;
  3. Fragment:组件化界面的根本单位;
  4. 布局:用 XML 中申明 UI 元素或者在代码中实例化 UI 元素;
  5. 调色板:从调色板中提取出有用的信息;

留神:

下面的图之前在官网是存在的,当初官网曾经找不到此图,只有 jetpack 架构组件的文档入口;

猜测 google 官网也是旨在强化 Architecture 架构组件,因为 UI、Behavior、Foundation 这三局部大多是对已有内容的收集整理。

所以接下来的关注点次要是在 Architecture 架构局部

4、Jetpack 与 AndroidX

参考官网 Jetpack 应用

1、Jetpack 库能够独自应用,也能够组合应用,以满足利用的不同需要。

2、Jetpack 库在 androidx 命名空间中公布。

androidx 介绍:

==androidx 命名空间中的工件蕴含 Android Jetpack 库。与反对库一样,androidx 命名空间中的库与 Android 平台离开提供,并向后兼容各个 Android 版本。==

==AndroidX 对原始 Android 反对库进行了重大改良,后者当初已不再保护。androidx 软件包齐全取代了反对库,不仅提供等同的性能,而且提供了新的库。==

AndroidX 还包含以下性能:

++AndroidX 中的所有软件包都应用统一的命名空间,以字符串 androidx 结尾。反对库软件包已映射到对应的 androidx.* 软件包。无关所有旧类到新类以及旧构建工件到新构建工件的残缺映射,请参阅软件包重构页面。++

++ 与反对库不同,androidx 软件包会独自保护和更新。从版本 1.0.0 开始,androidx 软件包应用严格的语义版本控制。您能够独自更新我的项目中的各个 AndroidX 库。++

++ 版本 28.0.0 是反对库的最初一个版本。咱们将不再公布 android.support 库版本。所有新性能都将在 androidx 命名空间中开发。++

所以,目前咱们的我的项目【朴新网校】、【朴新助教】、【数学宝典】都曾经迁徙应用了 androidx 库。

androidx 迁徙参照官网

留神:Jetpack 是各种组件库的统称,AndroidX 是这些组件的对立包名。

二、Jetpack 架构组件库

1、利用架构指南

官网举荐利用架构:

在我的项目中使用到的框架的搭建根本基于改图,使用到的 jetpack 组件库有ViewModelLiveDataDataBinding; 接下来逐个介绍他们的个性和用法。

2、ViewModel & LiveData

ViewModel 类旨在以重视生命周期的形式存储和治理界面相干的数据。ViewModel 类让数据可在产生屏幕旋转等配置更改后持续留存。

LiveData 是一种可察看的数据存储器类。与惯例的可察看类不同,LiveData 具备生命周期感知能力,意指它遵循其余利用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于沉闷生命周期状态的利用组件观察者。

LiveData,ViewModel 组件都是基于 Lifecycle 来实现的,LiveData&ViewModel 也是联合应用的,接下来具体看下如何应用

申明依赖项

dependencies {
        def lifecycle_version = "2.2.0"

        // ViewModel
        implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
        // LiveData
        implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
}

实现 ViewModel

架构组件为界面控制器提供了 ViewModel 辅助程序类,该类负责为界面筹备数据。在配置更改期间会主动保留 ViewModel 对象,以便它们存储的数据立刻可供下一个 Activity 或 Fragment 实例应用。例如,如果您须要在利用中显示用户列表,请确保将获取和保留该用户列表的责任调配给 ViewModel,而不是 Activity 或 Fragment,如以下示例代码所示:

public class MyViewModel extends ViewModel {
        private MutableLiveData<List<User>> users;
        public LiveData<List<User>> getUsers() {if (users == null) {users = new MutableLiveData<List<User>>();
                loadUsers();}
            return users;
        }

        private void loadUsers() {// Do an asynchronous operation to fetch users.}
    }
    

而后,您能够从 Activity 拜访该列表,如下所示:

public class MyActivity extends AppCompatActivity {public void onCreate(Bundle savedInstanceState) {// Create a ViewModel the first time the system calls an activity's onCreate() method.
            // Re-created activities receive the same MyViewModel instance created by the first activity.

            MyViewModel model = new ViewModelProvider(this).get(MyViewModel.class);
            model.getUsers().observe(this, users -> {// update UI});
        }
    }
    

ViewModel 在 Fragment 之间共享数据

应用 ViewModel 对象解决这一常见的难点。这两个 Fragment 能够应用其 Activity 范畴共享 ViewModel 来解决此类通信

public class SharedViewModel extends ViewModel {private final MutableLiveData<Item> selected = new MutableLiveData<Item>();

        public void select(Item item) {selected.setValue(item);
        }

        public LiveData<Item> getSelected() {return selected;}
    }

    // 获取 ViewModelProvider 时, 会收到雷同的 SharedViewModel 实例(其范畴限定为该 Activity)public class MasterFragment extends Fragment {
        private SharedViewModel model;

        public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);
            // 通过 requireActivity() Fragment 会检索蕴含它们的 Activity
            model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
            itemSelector.setOnClickListener(item -> {model.select(item);
            });
        }
    }

    // 获取 ViewModelProvider 时, 会收到雷同的 SharedViewModel 实例(其范畴限定为该 Activity)public class DetailFragment extends Fragment {public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);
            // 通过 requireActivity() Fragment 会检索蕴含它们的 Activity
            SharedViewModel model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
            model.getSelected().observe(getViewLifecycleOwner(), { item ->
               // Update the UI.
            });
        }
    }
    

该办法的劣势:

  • Activity 不须要执行任何操作,也不须要对此通信有任何理解。
  • 除了 SharedViewModel 约定之外,Fragment 不须要相互了解。如果其中一个 Fragment 隐没,另一个 Fragment 将持续照常工作。
  • 每个 Fragment 都有本人的生命周期,而不受另一个 Fragment 的生命周期的影响。如果一个 Fragment 替换另一个 Fragment,界面将持续工作而没有任何问题。

应用 LiveData 对象

官网应用参考

1、创立 LiveData 对象

LiveData 是一种可用于任何数据的封装容器,其中包含可实现 Collections 的对象,如 List。LiveData 对象通常存储在 ViewModel 对象中,并可通过 getter 办法进行拜访,如以下示例中所示:

public class NameViewModel extends ViewModel {

    // Create a LiveData with a String
    private MutableLiveData<String> currentName;

        public MutableLiveData<String> getCurrentName() {if (currentName == null) {currentName = new MutableLiveData<String>();
            }
            return currentName;
        }

    // Rest of the ViewModel...
    }

最后,LiveData 对象中的数据并未通过设置。

留神:请确保用于更新界面的 LiveData 对象存储在 ViewModel 对象中,而不是将其存储在 Activity 或 Fragment 中,起因如下:1、防止 Activity 和 Fragment 过于宏大。当初,这些界面控制器负责显示数据,但不负责存储数据状态。2、将 LiveData 实例与特定的 Activity 或 Fragment 实例分来到,并使 LiveData 对象在配置更改后持续存在。

2、察看 LiveData 对象

在大多数状况下,在利用组件的 onCreate() 办法是开始察看 LiveData 对象起因如下:

1、确保零碎不会从 Activity 或 Fragment 的 onResume() 办法进行冗余调用。

2、确保 Activity 或 Fragment 变为沉闷状态后具备能够立刻显示的数据。一旦利用组件处于 STARTED 状态,就会从它正在察看的 LiveData 对象接管最新值。只有在设置了要察看的 LiveData 对象时,才会产生这种状况。

LiveData 仅在数据产生更改时才发送更新,并且仅发送给沉闷观察者。此行为的一种例外情况是,观察者从非沉闷状态更改为沉闷状态时也会收到更新。此外,如果观察者第二次从非沉闷状态更改为沉闷状态,则只有在自上次变为沉闷状态以来值产生了更改时,它才会收到更新。

以下示例代码阐明了如何开始察看 LiveData 对象:

    public class NameActivity extends AppCompatActivity {

        private NameViewModel model;

        @Override
        protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);

            // Other code to setup the activity...

            // Get the ViewModel.
            model = new ViewModelProvider(this).get(NameViewModel.class);

            // Create the observer which updates the UI.
            final Observer<String> nameObserver = new Observer<String>() {
                @Override
                public void onChanged(@Nullable final String newName) {
                    // Update the UI, in this case, a TextView.
                    nameTextView.setText(newName);
                }
            };

            // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
            model.getCurrentName().observe(this, nameObserver);
        }
    }
    

3、更新 LiveData 对象

LiveData 没有公开可用的办法来更新存储的数据。MutableLiveData 类将公开 setValue(T) 和 postValue(T) 办法,如果您须要批改存储在 LiveData 对象中的值,则必须应用这些办法。通常状况下会在 ViewModel 中应用 MutableLiveData,而后 ViewModel 只会向观察者公开不可变的 LiveData 对象。

设置观察者关系后,您能够更新 LiveData 对象的值(如以下示例中所示),这样当用户点按某个按钮时会触发所有观察者:

    button.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            String anotherName = "John Doe";
            model.getCurrentName().setValue(anotherName);
        }
    });
    
留神:您必须调用 setValue(T) 办法以从主线程更新 LiveData 对象。如果在 worker 线程中执行代码,则您能够改用 postValue(T) 办法来更新 LiveData 对象。

3、Data Binding

Data Binding 是一种反对库,借助该库,您能够应用申明性情式(而非程序化地)将布局中的界面组件绑定到利用中的数据源。

布局通常是应用调用界面框架办法的代码在 Activity 中定义的。例如,以下代码调用 findViewById() 来查找 TextView 微件并将其绑定到 viewModel 变量的 userName 属性:

    TextView textView = findViewById(R.id.sample_text);
    textView.setText(viewModel.getUserName());

以下示例展现了如何在布局文件中应用 Data Binding 将文本间接调配到 TextView。这样就无需调用上述任何 Java 代码。请留神赋值表达式中 @{} 语法的应用:

<TextView
        android:text="@{viewmodel.userName}" />
    

留神

如果您应用 Data Biding 的次要目标是取代 findViewById() 调用,请思考改用 ViewBinding。

应用过 ButterKnife 的都晓得,目前 ButterKnife 作者倡议切换至 ViewBindng 应用;在许多状况下,ViewBinding 可简化实现,进步性能,提供与 DataBinding 雷同的益处。

Data Binding 应用场景:

布局和绑定表达式

数据绑定的布局以根标记 layout 结尾,后跟 data 元素和 view 根元素。如下:

留神:布局表达式应放弃精简,因为它们无奈进行单元测试,并且领有的 IDE 反对也无限。为了简化布局表达式,能够应用自定义绑定适配器。

<?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android">
        
        <!--data 中的 user 变量形容了可在此布局中应用的属性。-->
       <data>
           <variable name="user" type="com.example.User"/>
       </data>
       <LinearLayout
           android:orientation="vertical"
           android:layout_width="match_parent"
           android:layout_height="match_parent">
           <!-- 布局中的表达式应用“@{}”语法给控件赋值。-->
           <TextView android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:text="@{user.firstName}"/>
           <TextView android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:text="@{user.lastName}"/>
       </LinearLayout>
    </layout>
    

== 零碎会为每个布局文件生成一个绑定类 ==。

1、默认状况下,类名称基于布局文件的名称,它会转换为驼峰模式并在开端增加 Binding 后缀。

2、以上布局文件名为 activity_main.xml,因而生成的对应类为 ActivityMainBinding,== 且都是 ViewDataBinding 的子类,所有布局对应的生成的绑定类都能够是 ViewDataBinding 类 ==

3、此类蕴含从布局属性(例如,user 变量)到布局视图的所有绑定,并且晓得如何为绑定表达式指定值。

4、倡议的绑定创立办法是在裁减布局时创立,如以下示例所示:

    @Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
       ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
       User user = new User("Test", "User");
       binding.setUser(user);
    }

    

a、Activity 数据绑定 (DataBinding) :

1、DataBindingUtil 类办法:

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

2、生成的布局绑定类的 inflate()办法:

ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());

    @Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
       //DataBindingUtil 类办法
       ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
       // 生成的布局绑定类的 inflate()办法
       //ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
       User user = new User("Test", "User");
       binding.setUser(user);
    }

    

b、Fragment、ListView 或 RecyclerView 适配器中应用数据绑定 (DataBinding)

DataBindingUtil 或 生成的布局绑定类 deinflate() 办法,如以下代码示例所示:

    ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
    // or
    ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);

    
Data Binding 绑定表达式:

xml 里反对应用以下表达式:

  • 算术运算符 + – / * %
  • 字符串连贯运算符 +
  • 逻辑运算符 && ||
  • 二元运算符 & | ^
  • 一元运算符 + – ! ~
  • 移位运算符 >> >>> <<
  • 比拟运算符 == > < >= <=(请留神,< 须要本义为 <)
  • instanceof
  • 分组运算符 ()
  • 字面量运算符 – 字符、字符串、数字、null
  • 类型转换
  • 办法调用
  • 字段拜访
  • 数组拜访 []
  • 三元运算符 ?:

不反对以下表达式:

  • this
  • super
  • new
  • 显式泛型调用
a、变量

1、生成的数据绑定代码会主动查看有没有 null 值并避免出现 Null 指针异样。

2、例如,在表达式 @{user.name} 中,如果 user 为 Null,则为 user.name 调配默认值 null。

3、如果您援用 user.age,其中 age 的类型为 int,则数据绑定应用默认值 0。

<!-- 变量给控件赋值 -->
android:text="@{user.name}"

<!-- 控件给变量赋值(双向绑定)-->
android:text="@={user.name}"
b、Null 合并运算符(空运算符)

如果右边运算数不是 null,则 Null 合并运算符 (??) 抉择右边运算数,如果右边运算数为 null,则抉择左边运算数。

android:text="@{user.displayName ?? user.lastName}"
// 等效于如下三目表达式
android:text="@{user.displayName != null ? user.displayName : user.lastName}"
c、视图援用

1、表达式能够通过以下语法按 ID 援用布局中的其余视图:

2、绑定类将 ID 转换为驼峰式大小写。

3、在以下示例中,TextView 视图援用同一布局中的 EditText 视图:android:text=”@{exampleText.text}”

<EditText
    android:id="@+id/example_text"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"/>
    
<TextView
    android:id="@+id/example_output"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{exampleText.text}"/>
    
d、显示暗藏管制

1、首先在 xml 的 data 节点中援用 View

2、而后设置 visibility

<data>
    <import type="android.view.View"/>
</data>

android:visibility="@{student.boy ? View.VISIBLE : View.INVISIBLE}"
e、事件处理

办法援用:

==android:onClick=”@{handlers::onClickFriend}”==

绑定表达式可将视图的点击监听器调配给 MyHandlers 类的 onClickFriend() 办法,如下所示:

    public class MyHandlers {public void onClickFriend(View view) {...}
    }

    
<?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android">
       <data>
           <variable name="handlers" type="com.example.MyHandlers"/>
           <variable name="user" type="com.example.User"/>
       </data>
       <LinearLayout
           android:orientation="vertical"
           android:layout_width="match_parent"
           android:layout_height="match_parent">
           <TextView android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:text="@{user.firstName}"
               android:onClick="@{handlers::onClickFriend}"/>
       </LinearLayout>
    </layout>
    

留神:

1、在表达式中,您能够援用合乎监听器办法签名的办法。

2、当表达式求值后果为办法援用时,数据绑定会将办法援用和所有者对象封装到监听器中,并在指标视图上设置该监听器。

3、如果表达式的求值后果为 null,则数据绑定不会创立监听器,而是设置 null 监听器。

4、表达式中的办法签名必须与监听器对象中的办法签名完全一致。

监听器绑定:

==android:onClick=”@{() -> presenter.onSaveClick(task)}”==

绑定表达式可将视图的点击事件绑定打给 Presenter 类的 onSaveClick(Task task) 办法,如下所示:

    public class Presenter {public void onSaveClick(Task task){}}

    
<?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android">
        <data>
            <variable name="task" type="com.android.example.Task" />
            <variable name="presenter" type="com.android.example.Presenter" />
        </data>
        <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent">
            <Button android:layout_width="wrap_content" android:layout_height="wrap_content"
            android:onClick="@{() -> presenter.onSaveClick(task)}" />
        </LinearLayout>
    </layout>
    

以上,咱们尚未定义传递给 onClick(View) 的 view 参数。

监听器绑定提供两个监听器参数选项:您能够疏忽办法的所有参数,也能够命名所有参数。

如果您想命名参数,则能够在表达式中应用这些参数。

例如,下面的表达式能够写成如下模式:

android:onClick="@{(view) -> presenter.onSaveClick(task)}"
    

或者,如果您想在表达式中应用参数,则采纳如下模式:

    public class Presenter {public void onSaveClick(View view, Task task){}}

    
android:onClick="@{(theView) -> presenter.onSaveClick(theView, task)}"
    

监听长按事件,表达式应返回一个布尔值。

    public class Presenter {public boolean onLongClick(View view, Task task) {}}

    
android:onLongClick="@{(theView) -> presenter.onLongClick(theView, task)}"
    

留神:

1、监听器绑定这些是在事件产生时进行求值的 lambda 表达式。

2、数据绑定始终会创立一个要在视图上设置的监听器。

3、事件被分派后,监听器会对 lambda 表达式进行求值。

< END >

【Android 进化之路】

微信扫描二维码,关注我的公众号。

退出移动版