您当前的位置:首页 > 电脑百科 > 程序开发 > 移动端 > Android

Android Jetpack 架构浅析

时间:2020-12-03 12:56:22  来源:  作者:

作者:heiyulong

原文: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 的构成

Android Jetpack 架构浅析

 

如上图:Jetpack 主要包括 4 个部分,分别是【Architecture:架构】、【UI:界面】、【behavior:行为】和【foundation:基础】。

Architecture,架构组件

目的:帮助开发者设计稳健、可测试且易维护的应用;

  1. Lifecycle:具备宿主生命周期感知能力的组件 特性:持有组件(如 Activity 或 Fragment)生命周期状态的信息,并且允许其他对象观察此状态;
  2. LiveData:新一代具备生命周期感知能力的数据订阅、分发组件 特性:支持共享资源、支持黏性事件的分发、不再需要手动处理生命周期、确保界面符合数据状态;
  3. ViewModel:具备生命周期感知能力的数据存储组件 特性:页面因配置变更导致的重启,此时数据不丢失;可以实现跨页面(跨 Activity)的数据共享;
  4. SavedState 架构组件原理解析 特性:因内存不足,电量不足导致页面被回收时可以搭配 ViewModel 实现数据存储与恢复;
  5. Room:轻量级 orm 数据库,本质上是一个 SQLite 抽象层 特性:使用简单(类似于 Retrofit 库),通过注解的方式实现相关功能,编译时自动生成相关实现类
  6. DataBinding:只是一种工具,解决的是 View 和数据之间的双向绑定 特性:支持数据与视图双向绑定、数据绑定空安全、减少模板代码、释放 Activity/Fragment 压力;
  7. Paging: 列表分页组件,可以轻松完成分页预加载以达到无限滑动的效果 特性:巧妙融合 LiveData、提供多种数据源加载方式;不足之处:不支持列表数据增删改,列表添加 HeaderView,FooterView 定位不准确;
  8. Navigation 组件原理分析:端内统一路由组件 特性:能够为 Activity,Fragment,Dialog,FloatWindow 提供统一的路由导航服务,可以传递参数,指定导航动画,还支持深度链接等主要能力;不足:十分依赖 xml 配置文件不利于组件化,模块化
  9. 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 架构部分

Android Jetpack 架构浅析

 

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、应用架构指南

官网推荐应用架构:

Android Jetpack 架构浅析

 

在项目中运用到的框架的搭建基本基于改图,运用到的jetpack组件库有ViewModel、LiveData、DataBinding;接下来逐一介绍他们的特性和用法。

2、ViewModel & LiveData

ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。


专栏
Go语言Web开发从入门到项目实战
作者:猿芯
18币
19人已购
查看

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是一种支持库,借助该库,您可以使用声明性格式(而非程序化地)将布局中的界面组件绑定到应用中的数据源。


专栏
Spring Cloud Alibaba微服务实战
作者:猿芯
36币
68人已购
查看

布局通常是使用调用界面框架方法的代码在 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 表达式进行求值。

Android Jetpack 架构浅析

 

后台私信回复 1024 免费领取 SpringCloud、SpringBoot,微信小程序、Java面试、数据结构、算法等全套视频资料。



Tags:Android   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
Android logcat日志封装logcat痛点在Android开发中使用logcat非常频繁,logcat能帮我们定位问题,但是在日常使用中发现每次使用都需要传递tag,并且会遇到输出频率很高的log,在多...【详细内容】
2021-12-22  Tags: Android  点击:(7)  评论:(0)  加入收藏
一、 准备工作1、安装JDK,下载地址(可能需要一个oracle账号,大家百度一下或者自行注册一个就行。尽可能选择8或者11,这两个是长期版本)Java SE | Oracle Technology Network | Or...【详细内容】
2021-11-23  Tags: Android  点击:(26)  评论:(0)  加入收藏
如果你是一名忠实的Android玩家,那么可能会知道,今年的Android 12系统在版本规划上与“往届”相比可以说是很有些特殊。具体来说,除了前段时间刚刚推出正式版的Android 12外,谷...【详细内容】
2021-11-10  Tags: Android  点击:(23)  评论:(0)  加入收藏
使用Maven Publish Plugin插件。(官方支持)一、在Library的build.gradle中配置plugins { id &#39;com.android.library&#39; id &#39;kotlin-android&#39; id &#39;k...【详细内容】
2021-11-05  Tags: Android  点击:(36)  评论:(0)  加入收藏
今年5月,谷歌推出了Android 12,这是原生安卓系统史上最大的设计变化,10月4日,谷歌推出全新的Android12正式版本,并且宣布会在今年晚些时候应用于安卓设备,对比Android11的挤牙膏式...【详细内容】
2021-10-29  Tags: Android  点击:(125)  评论:(0)  加入收藏
今天凌晨,谷歌正式发布了全新一代安卓Android 12系统,拥有全新的UI,同时带来了六大新功能,除此以外还有10月的安全补丁,下面就给大家介绍这六大新功能以及安卓Android 12系统配置...【详细内容】
2021-10-22  Tags: Android  点击:(53)  评论:(0)  加入收藏
用户通过系统返回按钮导航回去的一组页面,在开发中被称为返回栈 (back stack)。多返回栈即一堆 "返回栈",对多返回栈的支持是在 Navigation 2.4.0-alpha01 和 Fragment 1.4.0...【详细内容】
2021-08-17  Tags: Android  点击:(75)  评论:(0)  加入收藏
前言耗电量指标 待机时间成关注目标 提升用户体验 通过不同的测试场景,找出app高耗电的场景并解决01需要的环境准备1、python2.7(必须是2.7,3.X版本是不支持的) 2、golang语言...【详细内容】
2021-08-04  Tags: Android  点击:(93)  评论:(0)  加入收藏
6 月 29 日,微软向 Windows 预览体验计划的 Dev 通道推送了 Windows 11 的第一个预览版本,我们也在第一时间升级到了最新系统,可以点击这里查看 APPSO 的抢先体验。 关于 Windo...【详细内容】
2021-07-14  Tags: Android  点击:(90)  评论:(0)  加入收藏
玩过王者荣耀的朋友,几乎无人不晓「鲁班七号」这个英雄。作为 Android 的应用程序包,「APK」对于资深 Android 用户来说,知名度并不亚于前者。 也正因如此,日前 Google 的一份声...【详细内容】
2021-07-08  Tags: Android  点击:(44)  评论:(0)  加入收藏
▌简易百科推荐
今天面试遇到同学说做过内存优化,于是我一般都会问那 Bitmap 的像素内存存在哪?大多数同学都回答在 java heap 里面,就比较尴尬,理论上你做内存优化,如果连图片这个内存大户内存...【详细内容】
2021-12-23  像程序那样思考    Tags:Android开发   点击:(6)  评论:(0)  加入收藏
Android logcat日志封装logcat痛点在Android开发中使用logcat非常频繁,logcat能帮我们定位问题,但是在日常使用中发现每次使用都需要传递tag,并且会遇到输出频率很高的log,在多...【详细内容】
2021-12-22  YuCoding    Tags:Android   点击:(7)  评论:(0)  加入收藏
对项目的基本介绍 1.整个框架主要是给MVVM框架使用的,自己写完interface接口后,通过自定义的注解就能自动生成接口方法 2.用Kotlin的Flow去代替Rxjava,因为我发现RxJava功能很...【详细内容】
2021-12-08  网易Leo    Tags:Android开发   点击:(16)  评论:(0)  加入收藏
前言在Android开发过程中,有些时候会根据需要引用别的项目到当前项目里面,而且以Module形式引用。所以本篇博文就来分享一下怎么以Module形式引用别的项目到当前项目中,方便开...【详细内容】
2021-12-07  网易Leo    Tags:Android开发   点击:(21)  评论:(0)  加入收藏
作者:fundroid这篇文章偏阅读一些,大家可以了解下 Android 的一些最新动向。每年9/10月份 Google 都会举行约为期2天的 Android Dev Summit,在活动上 Google 的技术专家们会分...【详细内容】
2021-11-30  像程序那样思考    Tags:Android开发   点击:(15)  评论:(0)  加入收藏
一、 准备工作1、安装JDK,下载地址(可能需要一个oracle账号,大家百度一下或者自行注册一个就行。尽可能选择8或者11,这两个是长期版本)Java SE | Oracle Technology Network | Or...【详细内容】
2021-11-23  永沧    Tags:Android   点击:(26)  评论:(0)  加入收藏
使用Maven Publish Plugin插件。(官方支持)一、在Library的build.gradle中配置plugins { id &#39;com.android.library&#39; id &#39;kotlin-android&#39; id &#39;k...【详细内容】
2021-11-05  羊城小阳    Tags:Android   点击:(36)  评论:(0)  加入收藏
谷歌离推出Play Store应用程序的新数据隐私部分又近了一步。应用程序开发人员现在可以通过谷歌在Play控制台的新 "数据安全表 "填写相关细节。该公司表示,所需信息将从2022年...【详细内容】
2021-10-20    中关村在线  Tags:安卓   点击:(57)  评论:(0)  加入收藏
架构究竟是什么?如何更好的理解架构?我们知道一个APP通常是由class组成,而这些class之间如何组合,相互之间又如何产生作用,就是影响这个APP的关键点。细分的话我们可以将其分为类...【详细内容】
2021-09-17  像程序那样思考    Tags:Android架构   点击:(51)  评论:(0)  加入收藏
概述当Android应用程序需要访问设备上的敏感资源时,应用程序开发人员会使用权限模型。虽然该模型使用起来非常简单,但开发人员在使用权限时容易出错,从而导致安全漏洞。本文中,...【详细内容】
2021-09-07  SecTr安全团队    Tags:Android开发   点击:(66)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条