Android 业务架构 · 基础篇 · Jetpack 您所在的位置:网站首页 androidviewmodel Android 业务架构 · 基础篇 · Jetpack

Android 业务架构 · 基础篇 · Jetpack

#Android 业务架构 · 基础篇 · Jetpack| 来源: 网络整理| 查看: 265

文章目录: 4W2H 分析 Jetpack Jetpack 四件套( LifeCycle、LiveData、ViewModel 和 DataBing) 总结与展望 image.png 4W2H 分析 Jetpack 2.1 :What: Jetpack 是什么? image.png

定义:Android Jetpack 是一组 Android 软件组件、工具和指南,它们可以帮助开发者构建高质量、稳定的 Android 应用程序。Jetpack 中包含多个库,它们旨在解决 Android 应用程序开发中的常见问题,并提供一致的 API 和开发体验。 Jetpack 中包含的库包括:

ViewModel:帮助管理 UI 组件的生命周期并存储和管理 UI 相关的数据 LiveData:提供了响应式编程的功能,可以让数据在数据源发生变化时自动更新 UI。 Room:提供了一个抽象层,可以让开发者方便地访问和管理 SQLite 数据库 Navigation:提供了一种简单、一致的方式来处理应用程序的导 WorkManager:提供了一种简单、可靠的方式来管理后台任务。 除此之外,Jetpack 还包括了诸如 Paging、Data Binding、Preferences、Security 等库,这些库都旨在简化开发过程并提高应用程序的性能和可靠性。 Where: 什么场景下使用 Jetpack?

Jetpack 适用于开发各种类型的 Android 应用程序,包括单页面应用程序、多页面应用程序、后台任务应用程序等。下面是一些适合使用 Jetpack 的场景:

构建大型应用程序:Jetpack 提供了一些库,如 ViewModel、LiveData 和 Navigation,可以帮助开发者更好地管理应用程序的生命周期、状态和导航,使得构建大型应用程序更加容易。

处理后台任****务:Jetpack 中的 WorkManager 库提供了一种简单、可靠的方式来管理后台任务,如数据同步、推送通知、文件上传等。

数据库访问:Jetpack 中的 Room 库提供了一个抽象层,可以让开发者方便地访问和管理 SQLite 数据库,使得数据存储和访问更加容易。

响应式编程:Jetpack 中的 LiveData 和 Data Binding 库提供了响应式编程的功能,可以让数据在数据源发生变化时自动更新 UI,提高应用程序的性能和可靠性。

代码重用:Jetpack 中的各种库都旨在解决 Android 应用程序开发中的常见问题,并提供一致的 API 和开发体验,使得代码重用更加容易。

Why: 为什么使用 Jetpack?

以下是使用 Jetpack 的一些好处:

更好的代码组织和可维护性:Jetpack 提供了一组库,这些库旨在解决 Android 应用程序开发中的常见问题,如生命周期管理、数据存储、后台任务处理等。使用 Jetpack 可以使代码更加模块化,易于维护。 更好的代码可读性:Jetpack 提供了一致的 API 和开发体验,可以使代码更加易于理解和阅读。 更好的开发效率:Jetpack 提供了一些库和工具,如 Navigation 和 Data Binding,可以帮助开发者更快地开发 Android 应用程序,提高开发效率。 更好的性能和可靠性:Jetpack 中的一些库,如 LiveData 和 WorkManager,提供了响应式编程和后台任务处理的功能,可以提高应用程序的性能和可靠性。 更好的向后兼容性:Jetpack 中的一些库,如 ViewModel 和 LiveData,提供了对 Android 不同版本的向后兼容性支持,可以使开发者更容易地编写适用于不同版本的 Android 系统的应用程序。综上所述,Jetpack 可以帮助开发者更好地组织代码、提高开发效率、提高应用程序的性能和可靠性,并提供了对不同版本的 Android 系统的向后兼容性支持。 Who: 什么样的团队该使用 Jetpack?

Jetpack 适用于各种规模的 Android 开发团队,特别是那些希望提高应用程序质量、开发效率和可维护性的团队。以下是一些团队适合使用 Jetpack 的场景:

大型团队:Jetpack 提供了一致的 API 和开发体验,可以使大型团队更容易协作开发,提高团队的开发效率和代码质量。 跨职能团队:Jetpack 提供了一些库和工具,如 Navigation 和 Data Binding,可以帮助开发者更快地开发 Android 应用程序,使得跨职能团队之间更容易协作。 需要提高应用程序性能和可靠性的团队:Jetpack 中的一些库,如 LiveData 和 WorkManager,提供了响应式编程和后台任务处理的功能,可以提高应用程序的性能和可靠性。 需要提高代码可维护性的团队:Jetpack 提供了一些库,如 ViewModel 和 Room,可以帮助开发者更好地管理应用程序的状态和数据,使得代码更易于维护。 需要保持向后兼容性的团队:Jetpack 中的一些库,如 ViewModel 和 LiveData,提供了对 Android 不同版本的向后兼容性支持,可以使开发者更容易地编写适用于不同版本的 Android 系统的应用程序。 综上所述,Jetpack 适合各种规模和类型的 Android 开发团队,特别是那些希望提高应用程序质量、开发效率和可维护性的团队。 How: 怎样使用 Jetpack?

以下是使用 Jetpack 的一般步骤:

添加 Jetpack 库:Jetpack 库可以通过在 build.gradle 文件中添加依赖项的方式进行添加。例如,添加 Lifecycle 库的依赖项:

dependencies { def lifecycle_version = "2.3.1"// ViewModel implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"// LiveData implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"// Lifecycle implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version" }

使用 Jetpack 库:在添加 Jetpack 库后,就可以在应用程序中使用 Jetpack 库提供的功能了。例如,使用 ViewModel 库创建一个 ViewModel 类:

import androidx.lifecycle.ViewModel class MyViewModel : ViewModel() { // Add ViewModel logic here }

结合 Jetpack 组件使用:Jetpack 库提供的组件可以结合使用,以提高应用程序的开发效率和可维护性。例如,使用 ViewModel 库和 LiveData 库实现一个响应式的用户界面:

class MyActivity : AppCompatActivity() { private lateinit var viewModel: MyViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_my) // Get a reference to the ViewModel viewModel = ViewModelProvider(this).get(MyViewModel::class.java) // Observe a LiveData object in the ViewModel viewModel.someData.observe(this, Observer { // Update the UI with the new data }) } }

以上是使用 Jetpack 的一般步骤。需要根据具体的 Jetpack 库和应用程序需求进行相应的配置和代码实现。

How Much: 使用 Jetpack 业务价值

使用 Jetpack 可以带来以下业务价值:

提高开发效率:Jetpack 提供了一些开发工具和库,例如 ViewModel、LiveData 和 Room,可以减少重复的编写代码,简化开发流程,并提高开发效率。 提高应用程序质量:Jetpack 提供了一致的 API 和开发体验,可以减少由于人为因素引起的代码错误,提高应用程序的质量。 提高应用程序性能:Jetpack 中的一些库,例如 Lifecycle 和 WorkManager,提供了响应式编程和后台任务处理的功能,可以提高应用程序的性能和响应速度。 简化应用程序架构:Jetpack 提供了一些组件和库,例如 ViewModel 和 Data Binding,可以帮助开发者更好地管理应用程序的状态和数据,并简化应用程序的架构。 支持向后兼容性:Jetpack 中的一些库,例如 ViewModel 和 LiveData,提供了对 Android 不同版本的向后兼容性支持,可以使开发者更容易地编写适用于不同版本的 Android 系统的应用程序。综上所述,使用 Jetpack 可以带来多种业务价值,可以提高应用程序的质量、性能和开发效率,同时简化应用程序架构和支持向后兼容性,可以使应用程序更易于维护和升级。 Jetpack 四件套 LifeCycle image.png 基础定义 Lifecycle 提供了一种轻松管理组件(如 Activity 和 Fragment)生命周期的方式,同时也支持自定义组件的生命周期。 Jetpack Lifecycle 提供了一组类和接口,使得开发者可以在组件的生命周期各个阶段执行相应的操作。 这些类和接口包括: LifecycleOwner: 拥有生命周期的对象,通常是 Activity 和 Fragment。 LifecycleObserver: 监听组件的生命周期事件的观察者对象。 Lifecycle: 组件的生命周期,包括 CREATED、STARTED、RESUMED、PAUSED、STOPPED、DESTROYED 等状态。 LiveData: 一个可观察的数据容器,可以在组件生命周期的不同阶段更新数据。 使用 Jetpack Lifecycle,可以更容易地避免内存泄漏和其他生命周期相关的问题。 例如,可以在组件被销毁时自动释放资源、取消网络请求等操作。 此外,Jetpack Lifecycle 还提供了一种方式来创建自定义的生命周期状态,以更好地满足 App 的需求。 总之,Jetpack Lifecycle 是 Android Jetpack 组件库中的一个重要组件,可以帮助开发者更轻松地管理组件的生命周期,从而提高 App 的质量和性能。 LifeCycle 基础使用

在 App 的主 Activity 中实现一个简单的计时器,当 Activity 处于前台时,计时器会不断递增,当 Activity 被销毁时,计时器将停止。

具体实现步骤如下:

在 gradle 文件中添加 Jetpack 组件库的依赖。 dependencies { implementation "androidx.lifecycle:lifecycle-extensions:2.4.0"} 创建一个名为 Timer 的 Java 类,并实现 LifeCycleObserver 接口。 public class Timer implements LifecycleObserver { private Handler handler; private int seconds = 0; @OnLifecycleEvent(Lifecycle.Event.ON_START)public void startTimer() { handler = new Handler(); handler.post(new Runnable() { @Overridepublic void run() { Log.d("Timer", "Seconds: " + seconds); seconds++; handler.postDelayed(this, 1000); } }); } @OnLifecycleEvent(Lifecycle.Event.ON_STOP)public void stopTimer() { handler.removeCallbacksAndMessages(null); handler = null; }} 在 MainActivity 中添加 LifecycleOwner,并在 onCreate 方法中添加 Observer。 public class MainActivity extends AppCompatActivity { @Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 获取LifecycleOwner对象LifecycleOwner lifecycleOwner = this; // 将Timer实例添加为Observer getLifecycle().addObserver(new Timer()); // ... } // ...}

这样,当 Activity 处于前台时,Timer 实例中的 startTimer 方法会被调用,计时器会开始递增; 当 Activity 被销毁时,Timer 实例中的 stopTimer 方法会被调用,计时器会停止。 这个例子展示了如何使用 Jetpack LifeCycle 组件来管理 App 组件的生命周期。 当 App 中存在需要在组件生命周期不同阶段执行的操作时,使用 LifeCycle 可以更方便地实现这些操作,同时避免了一些常见的生命周期问题。

LifeCycle 优势劣势 优势 管理生命周期方便 使用 LifeCycle 组件可以更方便地管理 App 组件的生命周期,避免了一些常见的生命周期问题,如内存泄漏和空指针异常等。 模块化编程 使用 LifeCycle 组件可以将 App 的业务逻辑分解为模块化的组件,每个组件负责管理自己的生命周期,便于代码复用和维护。 规范化编程 使用 LifeCycle 组件可以规范化 App 的开发,使代码更易于阅读、理解和维护。 支持多个组件 LifeCycle 组件支持多个组件进行生命周期管理,可以轻松地在多个组件之间共享状态和数据。 劣势 需要继承 LifecycleObserver:在实现 LifeCycle 功能的时候,需要继承 LifecycleObserver 接口,这会导致代码的继承关系稍微有点复杂。 需要添加注释:在使用 LifeCycle 组件的时候,需要添加一些注释来指示方法是在什么时候被调用,否则可能会出现一些难以诊断的问题。 LifeCycle 应用场景 Jetpack LifeCycle 组件的实际开发应用场景包括: Activity 和 Fragment 生命周期管理:使用 LifeCycle 组件可以更方便地管理 Activity 和 Fragment 的生命周期,避免了一些常见的生命周期问题,如内存泄漏和空指针异常等。 后台服务管理:使用 LifeCycle 组件可以更方便地管理后台服务的生命周期,可以在 App 退出后自动停止后台服务,避免了一些不必要的资源浪费。 数据库连接管理:使用 LifeCycle 组件可以更方便地管理数据库连接的生命周期,可以在 App 退出时自动关闭数据库连接,避免了一些不必要的资源浪费 网络请求管理:使用 LifeCycle 组件可以更方便地管理网络请求的生命周期,可以在 Activity 或 Fragment 销毁时自动取消网络请求,避免了一些不必要的网络请求。 视图控制器管理:使用 LifeCycle 组件可以更方便地管理视图控制器的生命周期,可以在 Activity 或 Fragment 销毁时自动清除视图控制器的状态,避免了一些不必要的状态保存和恢复操作。 LifeCycle 原理分析 类图

LifecycleOwner 表示拥有生命周期的组件,比如 Activity 和 Fragment。

Lifecycle 表示组件的生命周期,LifecycleObserver 表示一个组件的生命周期观察者。

LifecycleRegistry 是 Lifecycle 接口的一个实现类,它维护了一个生命周期状态机,用于记录组件的生命周期状态和生命周期事件。

LifecycleRegistry 提供了一系列方法,用于管理组件的生命周期状态和生命周期事件。当组件的生命周期事件发生变化时,LifecycleRegistry 会自动更新状态机,并通知所有的 LifecycleObserver 观察者对象,以便它们可以相应地更新自己的状态。

LifecycleOwner 可以通过 getLifecycle()方法获取到一个 Lifecycle 对象,然后将自己的生命周期观察者对象添加到 Lifecycle 对象中,从而实现对组件生命周期的监听。

当组件的生命周期事件发生变化时,Lifecycle 会自动通知所有的生命周期观察者对象,以便它们可以相应地更新自己的状态。

image.png

源码

Lifecycle 库的核心是 Lifecycle 接口和 LifecycleObserver 接口。

Lifecycle 接口定义了一组方法,用于将 LifecycleOwner 与 LifecycleObserver 进行关联。

public abstract class Lifecycle { //添加观察者 @MainThread public abstract void addObserver(@NonNull LifecycleObserver observer); //移除观察者 @MainThread public abstract void removeObserver(@NonNull LifecycleObserver observer); //获取当前状态 public abstract State getCurrentState();//生命周期事件,对应Activity生命周期方法 public enum Event { ON_CREATE, ON_START, ON_RESUME, ON_PAUSE, ON_STOP, ON_DESTROY, ON_ANY //可以响应任意一个事件 } //生命周期状态. (Event是进入这种状态的事件) public enum State { DESTROYED, INITIALIZED, CREATED, STARTED, RESUMED; //判断至少是某一状态 public boolean isAtLeast(@NonNull State state) { return compareTo(state) >= 0; } }

LifecycleObserver 接口定义了一组回调方法,用于接收 LifecycleOwner 的生命周期事件。

在 Lifecycle 库的实现中,Lifecycle 接口有两个重要的实现类,分别是 LifecycleRegistry 和 LifecycleOwner。

LifecycleRegistry 实现了 Lifecycle 接口,并提供了一组方法,用于管理 LifecycleOwner 的生命周期状态。

LifecycleOwner 是一个接口,用于标识拥有生命周期状态的对象,通常是 Activity 或 Fragment。

//androidx.activity.ComponentActivity,这里忽略了一些其他代码,我们只看Lifecycle相关public class ComponentActivity extends androidx.core.app.ComponentActivity implements LifecycleOwner{ ... private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this); ... @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mSavedStateRegistryController.performRestore(savedInstanceState); ReportFragment.injectIfNeededIn(this); //使用ReportFragment分发生命周期事件 if (mContentLayoutId != 0) { setContentView(mContentLayoutId); } } @CallSuper @Override protected void onSaveInstanceState(@NonNull Bundle outState) { Lifecycle lifecycle = getLifecycle(); if (lifecycle instanceof LifecycleRegistry) { ((LifecycleRegistry) lifecycle).setCurrentState(Lifecycle.State.CREATED); } super.onSaveInstanceState(outState); mSavedStateRegistryController.performSave(outState); } @NonNull @Override public Lifecycle getLifecycle() { return mLifecycleRegistry; }}

在 LifecycleRegistry 中,有一个名为 mObserverMap 的成员变量,用于存储 LifecycleObserver 对象和其关联的 EventObserver 对象。

当 LifecycleOwner 的生命周期状态更改时,LifecycleRegistry 会自动调用 mObserverMap 中与之相关联的 EventObserver 对象的相应方法,以便它们可以执行适当的操作。

//LifecycleRegistry.java //系统自定义的保存Observer的map,可在遍历中增删 private FastSafeIterableMap mObserverMap = new FastSafeIterableMap(); public void handleLifecycleEvent(@NonNull Lifecycle.Event event) { State next = getStateAfter(event);//获取event发生之后的将要处于的状态 moveToState(next);//移动到这个状态 } private void moveToState(State next) { if (mState == next) { return;//如果和当前状态一致,不处理 } mState = next; //赋值新状态 if (mHandlingEvent || mAddingObserverCounter != 0) { mNewEventOccurred = true; return; } mHandlingEvent = true; sync(); //把生命周期状态同步给所有观察者 mHandlingEvent = false; } private void sync() { LifecycleOwner lifecycleOwner = mLifecycleOwner.get(); if (lifecycleOwner == null) { throw new IllegalStateException("LifecycleOwner of this LifecycleRegistry is already" + "garbage collected. It is too late to change lifecycle state."); } while (!isSynced()) { //isSynced()意思是 所有观察者都同步完了 mNewEventOccurred = false; //mObserverMap就是 在activity中添加observer后 用于存放observer的map if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) { backwardPass(lifecycleOwner); } Entry newest = mObserverMap.newest(); if (!mNewEventOccurred && newest != null && mState.compareTo(newest.getValue().mState) > 0) { forwardPass(lifecycleOwner); } } mNewEventOccurred = false; } ... static State getStateAfter(Event event) { switch (event) { case ON_CREATE: case ON_STOP: return CREATED; case ON_START: case ON_PAUSE: return STARTED; case ON_RESUME: return RESUMED; case ON_DESTROY: return DESTROYED; case ON_ANY: break; } throw new IllegalArgumentException("Unexpected event value " + event); }

LifecycleRegistry 还提供了一组方法,如 handleLifecycleEvent()、getCurrentState()、addObserver()、removeObserver()等,用于管理组件的生命周期状态和 LifecycleObserver 对象。

在 Lifecycle 库的实现中,还有一些其他的类和接口,如 GenericLifecycleObserver、FullLifecycleObserver、LifecycleEvent、EventObserver 等,它们都是用于管理和处理组件生命周期事件的。

LifeCycle 注意事项

1,不要在 onCreate() 方法中使用 Lifecycle 组件

Lifecycle 组件在 onCreate() 方法中尚未初始化完成,因此在该方法中使用它们可能会导致崩溃或不可预测的行为。建议在 onStart() 方法中使用 Lifecycle 组件。

2,不要手动调用 onDestroy() 方法

手动调用 onDestroy() 方法会破坏 Lifecycle 组件的生命周期,从而导致应用程序行为异常。Lifecycle 组件应该由系统自动管理,应该避免手动干预。

3,避免在 Fragment 中使用多个 LifecycleOwner

Fragment 自身就是一个 LifecycleOwner,因此不应该在 Fragment 中创建其他的 LifecycleOwner。这样会导致多个 LifecycleOwner 之间的状态不同步,从而导致应用程序出现问题。

LiveData image.png LiveData 基础定义

Android Jetpack LiveData 是一种用于管理应用程序界面和数据交互的组件。

LiveData 是一种可观察的数据持有者,用于在应用程序组件(如 Activity、Fragment 和 Service)之间共享数据,并在数据发生更改时通知观察者。

LiveData 可以确保 UI 与数据的同步更新,避免了一些常见的错误,如内存泄漏和 UI 组件无法正确更新的问题。

LiveData 具有生命周期感知功能,可以自动感知应用程序组件的生命周期,并在组件处于活动状态时更新 UI,而在组件处于非活动状态时停止更新,从而有效地减少了资源消耗。

LiveData 还提供了线程安全的访问数据的机制,避免了多线程并发访问的问题。

LiveData 基础使用

如何 TextView 控件的显示内容呢?

首先,在 XML 布局文件中添加一个 TextView 控件:

然后,在 Activity 或 Fragment 中创建一个 LiveData 对象,用于更新 TextView 的显示内容:

public class MyActivity extends AppCompatActivity { private LiveData mLiveData; private TextView mTextView; @Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextView = findViewById(R.id.text_view); mLiveData = new MutableLiveData(); mLiveData.observe(this, new Observer() { @Overridepublic void onChanged(String s) { mTextView.setText(s); } }); }}

在上述代码中,我们创建了一个 LiveData 对象,并将其与一个 TextView 控件关联。当 LiveData 对象中的值发生变化时,我们使用 Observer 来监听这个变化,然后更新 TextView 的显示内容。

最后,我们可以在代码中通过 setValue() 或 postValue() 方法来更新 LiveData 对象的值,从而更新 TextView 的显示内容。例如:

((MutableLiveData) mLiveData).setValue("Hello, world!");

以上就是一个简单的 LiveData 案例,用于更新 TextView 控件的显示内容。当 LiveData 中的值发生变化时,TextView 控件会自动更新显示内容。

LiveData 优势劣势 优势

1. 生命周期感知:LiveData 可以感知组件(如 Activity 或 Fragment)的生命周期,从而避免了由于 UI 组件的生命周期变化而引发的空指针异常和内存泄漏等问题。2. 数据更新通知:LiveData 可以在数据发生变化时自动通知所有观察者更新数据,从而实现数据的实时更新和响应。3. 数据一致性:LiveData 可以确保在配置更改时保持数据的一致性,避免了数据丢失和重复加载等问题。4. 线程安全:LiveData 可以确保在主线程中更新 UI 界面,并支持在工作线程中进行异步操作,从而避免了多线程数据竞争问题。5. 与 ViewModel 结合使用:LiveData 可以与 ViewModel 结合使用,实现数据与 UI 界面的分离,从而提高了代码的可维护性和可测试性。

劣势

1. 适用场景有限:LiveData 适用于数据变化频繁、需要实时更新的场景,对于数据变化较少的场景,使用 LiveData 可能会增加代码复杂性。2. API 限制:LiveData 是 Android Jetpack 组件,只能在支持 Jetpack 的 Android 版本上使用,对于一些较老的 Android 版本可能需要使用其他技术方案。

LiveData 应用场景

LiveData 的应用场景包括但不限于以下几个方面:

数据库操作:LiveData 可以与 Room 持久化库结合使用,当数据库中的数据发生变化时,LiveData 会自动通知 UI 组件进行更新。2. 网络请求:LiveData 可以与 Retrofit 网络请求库结合使用,当网络请求的结果返回时,LiveData 会自动通知 UI 组件进行更新。3. 数据共享:LiveData 可以在不同的组件之间共享数据,例如,当一个 Activity 和一个 Fragment 需要共享数据时,可以将 LiveData 对象设置为一个公共的数据持有者。4. 资源释放:LiveData 可以在 UI 组件不再处于活动状态时自动释放资源,避免出现内存泄漏等问题。5. 代码简洁:LiveData 可以减少代码复杂度,通过数据观察者的方式,避免手动编写繁琐的数据更新代码。 LiveData 原理分析

LiveData 是一种可以感知生命周期的数据持有者,它可以让数据更新时通知 UI 界面进行更新,同时也能够避免因为生命周期问题带来的内存泄漏。

类图 LiveData 的简化类图: image.png

在上面的类图中,Observer 是 LiveData 的观察者接口,LiveData 是可观察数据的持有者类。LiveData 具有生命周期感知能力,可以根据其生命周期状态自动管理数据的订阅和取消订阅。MutableLiveData 是 LiveData 的可变子类,允许更新 LiveData 持有的数据。LiveData 的 observe()方法用于注册观察者,setValue()和 postValue()方法用于更新 LiveData 数据。

源码

LiveData 的核心代码在 androidx.lifecycle.LiveData 类中,下面对 LiveData 的源码进行简要分析:

1. LiveData 的基本结构

LiveData 类是一个抽象类,它有一个泛型类型 T,表示 LiveData 中存储的数据类型。LiveData 类内部维护了一个数据源(mData)和一个观察者列表(mObservers),当 LiveData 中的数据发生改变时,会通知所有注册的观察者进行 UI 更新。

public abstract class LiveData { private static final Object NOT_SET = new Object(); private Object mData; private boolean mDispatchingValue; private int mActiveCount; private volatile Object mPendingData = NOT_SET; private volatile Object mVersion = new Object(); private final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor(); private final SafeIterableMap mObservers = new SafeIterableMap(); // ...} 2. 观察者注册

LiveData 中的观察者是通过 observe()方法进行注册的,这个方法接受一个 LifecycleOwner 对象和一个 Observer 对象。LifecycleOwner 是一个具有生命周期的对象,当 LifecycleOwner 的生命周期结束时,LiveData 会自动解注册所有与该 LifecycleOwner 相关的观察者,避免内存泄漏。

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer Code

创建 DataBinding 实例,并将 activity_main.xml 布局文件与 DataBinding 实例绑定。然后,将计数器的值赋给 DataBinding 实例的 counter 变量,并为增加和减少按钮设置点击事件。在点击事件中,更新计数器的值,并将新的值赋给 DataBinding 实例的 counter 变量。最后,调用 DataBinding 实例的 executePendingBindings()方法,将 UI 组件的值更新到最新的值。

class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding private var counter = 0 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 创建DataBinding实例并与布局文件绑定 binding = DataBindingUtil.setContentView(this, R.layout.activity_main) // 设置初始值 binding.counter = counter // 为按钮设置点击事件 binding.btnIncrease.setOnClickListener { counter++ binding.counter = counter binding.executePendingBindings() } binding.btnDecrease.setOnClickListener { counter-- binding.counter = counter binding.executePendingBindings() } }} DataBinding 优势劣势 优势

1. 简化代码使用 DataBinding 可以减少 findViewById()方法的调用,使得代码更加简洁和易读。开发者可以通过 DataBinding 直接访问布局文件中的 UI 组件,而不需要手动查找和设置 UI 组件的属性。

2. 双向绑定DataBinding 支持双向绑定,可以将 UI 组件的值绑定到数据模型中的属性,也可以将数据模型的属性绑定到 UI 组件的值。这种双向绑定可以帮助开发者更加方便地实现 UI 和数据模型之间的同步。

3. 减少错误DataBinding 可以减少代码中的错误,因为使用 DataBinding 可以消除某些手动编写的代码。例如,DataBinding 可以自动生成一些代码,帮助开发者绑定 UI 组件和数据模型,减少手动编写代码的机会。

4. 性能优化DataBinding 可以带来一些性能优化,例如通过生成绑定类来减少代码的执行时间。DataBinding 还支持懒加载,可以在需要时才加载数据模型和 UI 组件。

劣势

1. 兼容性问题DataBinding 库需要使用较新的 Android Gradle 插件和 Android SDK 版本,这可能导致一些兼容性问题。如果开发者使用较老的 Android 版本,可能需要进行一些兼容性处理。

2. 构建时间增加使用 DataBinding 可能会增加应用程序的构建时间,因为 DataBinding 库需要生成绑定类。在较大的应用程序中,这可能会导致构建时间明显增加。

3. 难以调试由于 DataBinding 库使用了代码生成,因此在调试时可能会出现一些困难。例如,开发者可能会发现在使用 DataBinding 时,调试器可能会跳过某些代码行,或者某些变量的值可能无法正确显示。

DataBinding 应用场景 MVVM 架构:DataBinding 可以帮助开发者实现 MVVM 架构中的视图模型(ViewModel)和视图(View)之间的绑定。通过 DataBinding,开发者可以将视图和数据模型分离,提高代码的可读性和可维护性。2. 布局优化:DataBinding 可以帮助开发者实现布局优化,例如通过使用绑定表达式和条件语句来控制 UI 组件的可见性。通过布局优化,可以使得应用程序的 UI 更加灵活和可定制。3. 多语言支持:DataBinding 可以帮助开发者实现多语言支持,例如通过使用绑定表达式来动态设置 UI 组件的文本。通过多语言支持,可以使得应用程序的用户界面更加友好和易用。4. 动态主题:DataBinding 可以帮助开发者实现动态主题,例如通过使用绑定表达式来动态设置 UI 组件的颜色和样式。通过动态主题,可以使得应用程序的 UI 更加美观和精致。 DataBinding 原理分析 类图

[图片上传失败...(image-b6c52b-1681392230053)]

源码

DataBinding 的原理主要包括以下几个方面:

布局文件的解析和生成:在 DataBinding 中,布局文件会被解析并生成对应的 ViewDataBinding 类。这个类包含了布局文件中定义的所有 UI 组件的引用,以及绑定到这些 UI 组件的数据对象。2. 数据对象的绑****定:DataBinding 会在编译时生成代码来完成 UI 组件和数据对象的绑定。生成的代码会被包含在 BR 类中。这个类包含了应用程序中所有用于绑定的变量的引用。当数据对象发生变化时,DataBinding 会自动更新 UI 组件的值。3. 观察者模式的应用:DataBinding 使用观察者模式来保持 UI 和数据之间的同步。当数据对象发生变化时,DataBinding 会自动更新 UI 组件的值。在 DataBinding 中,数据对象是被观察的对象,而 UI 组件是观察者。4. 双向绑定的实现:DataBinding 支持双向绑定,即当 UI 组件的值发生变化时,DataBinding 会自动更新数据对象的值。这是通过使用双向绑定适配器来实现的。适配器会在 UI 组件的值发生变化时自动更新数据对象的值。5. 属性转换器的使用:DataBinding 还支持属性转换器,可以用来将数据对象中的值转换为 UI 组件可以显示的值。例如,可以使用属性转换器将日期格式化为特定的格式。6. 数据绑定表达式的应用:DataBinding 还支持数据绑定表达式,可以用来在布局文件中动态计算 UI 组件的值。例如,可以使用数据绑定表达式将两个文本框中的值相加并将结果显示在第三个文本框中。 总的来说,Android Jetpack DataBinding 的原理是基于数据绑定和观察者模式的。它通过生成代码来完成 UI 组件和数据对象之间的绑定,并使用观察者模式来保持 UI 和数据之间的同步。同时,DataBinding 还支持双向绑定、属性转换器和数据绑定表达式等特性,使得它可以满足更加复杂的 UI 和数据交互需求。 DataBinding 注意事项 错误:Cannot find the setter for attribute ‘XXX’ with parameter type XXX。这个错误通常是由于绑定表达式中的变量类型不正确或布局文件中的属性名称不正确导致的。可以检查变量类型和属性名称是否正确。2. 错误:Could not find accessor XXX。这个错误通常是由于布局文件中使用了不存在的变量或方法导致的。可以检查布局文件中使用的变量和方法是否存在。3. 错误:Variable XXX has incompatible type XXX。这个错误通常是由于 DataBinding 的变量类型和布局文件中的变量类型不一致导致的。可以检查 DataBinding 代码中变量的类型和布局文件中变量的类型是否一致。4. 错误:DataBinding 不支持 lambda 表达式。如果使用 lambda 表达式,编译时会出现错误。可以使用方法引用或匿名内部类来替代 lambda 表达式。5. 性能问题:在使用数据绑定表达式时,要注意表达式的复杂度。复杂的表达式可能会影响应用程序的性能。可以尝试将复杂的表达式分解成更简单的表达式,以提高应用程序的性能。6. 混淆问题:如果应用程序使用了代码混淆,那么需要将 DataBinding 的类排除在混淆范围之外,否则会导致编译错误或运行时异常。7. ViewStub 问题:在使用 DataBinding 的布局文件中,不能包含 ViewStub,否则会导致编译错误。 ButterKnife VS ViewBinding VS RoboBinding VS DataBinding image.png

总结与展望

《Android 业务架构 · 基础篇 · Jetpack 四件套》一文首先通过 4W2H 全方位的讲解了 Jepack 对 Android 业务开发的价值,然后通过基础定义、基础使用、优劣势分析、应用场景、原理分析、注意事项等多维度分析了 Jetpack 四件套。

在我们工作中,可维护、可扩展、可测试和可重用的业务架构对于提高应用程序的质量和效率意义非凡,而 JetPack 是帮助开发者快速地组织和管理应用程序的代码的工具包。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有