回顾原生开发

在Android原生开发中,通常是使用Databinding实现MVVM架构,只需要在gradle中开启databinding的选项,然后使用ObservableField或LiveData即可。

buildFeatures {dataBinding true}
 

在ViewModel中可以定义ObservableField,这样界面就可以直接观察了。简单看一下ObservableField的源码,其实还有另外的几个类也是类似的功能,比如ObservableInt和ObservableBoolean。

package androidx.databinding;import androidx.annotation.Nullable;import java.io.Serializable;/** * An object wrapper to make it observable. * 

* Observable field classes may be used instead of creating an Observable object. It can also * create a calculated field, depending on other fields: *

public class MyDataObject { * private Context context; * public final ObservableField<String> first = new ObservableField<String>(); * public final ObservableField<String> last = new ObservableField<String>(); * public final ObservableField<String> display = * new ObservableField<String>(first, last) { * Override * public String get() { * return context.getResources().getString(R.string.name, first.get, last.get()); * } * }; * public final ObservableInt age = new ObservableInt(); * }

* Fields of this type should be declared final because bindings only detect changes in the * field's value, not of the field itself. * * @param The type parameter for the actual object. * @see ObservableParcelable */public class ObservableField extends BaseObservableField implements Serializable {static final long serialVersionUID = 1L;private T mValue;/** * Wraps the given object and creates an observable object * * @param value The value to be wrapped as an observable. */public ObservableField(T value) {mValue = value;}/** * Creates an empty observable object */public ObservableField() {}/** * Creates an ObservableField that depends on {@code dependencies}. Typically, * ObservableFields are passed as dependencies. When any dependency * notifies changes, this ObservableField also notifies a change. * * @param dependencies The Observables that this ObservableField depends on. */public ObservableField(Observable... dependencies) {super(dependencies);}/** * @return the stored value. */@Nullablepublic T get() {return mValue;}/** * Set the stored value. * * @param value The new value */public void set(T value) {if (value != mValue) {mValue = value;notifyChange();}}}

databinding里面的ObservableField类可以帮助我们很好的实现数据的双向绑定,通过调用它 的get()方法就可以拿到值了,在xml中也可以很方便地使用其值。 这样一种优雅的写法,在Flutter中怎么玩呢?还是那句话,巧妇难为无米之炊,首先你得有Flutter的开发环境,要不然你也就只能看看了。如果不了解Flutter环境怎么搭建的可以看juejin.cn/post/718557… 这篇文章。那么我们开向幼儿园的车马上就要发车了。不好意思,说错了,是开往大前端大佬的车。

框架搭建

我们先大概了解下Flutter项目的项目结构,由于这是一个演示Demo,我这里就不分包了,你们可以写的更优雅。集成get框架就一个命令,flutter就是这么简单。

flutter pub add get

内行人一眼就看出我们肯定是先看main.dart文件。

import 'package:flutter/material.dart';import 'package:flutter_mvvm_demo/home_binding.dart';import 'package:flutter_mvvm_demo/main_binding.dart';import 'package:flutter_mvvm_demo/home_view.dart';import 'package:flutter_mvvm_demo/main_view.dart';import 'package:get/get.dart';void main() {runApp(const MyApp());}class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return GetMaterialApp(initialRoute: '/home',getPages: [GetPage(name: '/home',page: () => const HomeView(),binding: HomeBinding(),),GetPage(name: '/main',page: () => const MainView(),binding: MainBinding(),),],);}}

这个MyApp就是我们程序的入口,相当于Application类,其实最主要是因为在main()方法中调了一个runApp()方法,然后传入了我们的第一个视图。在Flutter中,不是管View叫视图。Flutter中的视图有两种,一种是有状态的StatefulWidget,还有一种是无状态的StatelessWidget。我们这里返回了一个GetMaterialApp,里面指定了两个属性。initialRoute代表第一个页面的路由,getPages中指定所有的页面。GetPage里面的page指定了这个页面的视图Widget,然后使用binding指定依赖注入,简单说就是不用在使用的时候new对象,直接注入到属性中。

import 'package:flutter_mvvm_demo/home_controller.dart';import 'package:get/get.dart';class HomeBinding extends Bindings {@overridevoid dependencies() {Get.put(HomeController());}}
import 'package:flutter_mvvm_demo/main_controller.dart';import 'package:get/get.dart';class MainBinding extends Bindings {@overridevoid dependencies() {Get.put(MainController());}}

调用Get.put()方法我们就注入了controller,之后我们可以直接在视图层拿到这个controller。

import 'package:flutter/material.dart';import 'package:flutter_mvvm_demo/home_controller.dart';import 'package:get/get.dart';class HomeView extends GetView {const HomeView({super.key});@overrideWidget build(BuildContext context) {return Center(child: ElevatedButton(onPressed: () {Get.toNamed('/main');}, child: const Text('跳转主界面')) ,);}}
import 'package:flutter/material.dart';import 'package:flutter_mvvm_demo/main_controller.dart';import 'package:get/get.dart';class MainView extends GetView {const MainView({super.key});@overrideWidget build(BuildContext context) {return Obx(() => Row(children: [Text('${controller.count}'),ElevatedButton(onPressed: () {controller.plus();}, child: const Text('+'))]));}}

视图层我们直接继承GetView比较方便,这样可以直接拿到之前注入的controller。使用Obx括起来的内容,当被观察的属性值被修改时,直接更新Obx里面的界面。我们再来看一看怎么定义可以被观察的属性,类似于原生开发中ObservableField这样的。

import 'package:get/get.dart';class MainController extends GetxController {var count = 0.obs;plus() => count++;}

你没有看错,直接在属性值的地方加一个.obs就可以了。这样count的值一旦被修改,就会通知刷新Obs括起来的界面。

作者:dora
链接:https://juejin.cn/post/7200775196113895483

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。


相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

全套视频资料:

一、面试合集

二、源码解析合集


三、开源框架合集


欢迎大家一键三连支持,若需要文中资料,直接点击文末CSDN官方认证微信卡片免费领取↓↓↓