当前位置:   article > 正文

鸿蒙flutter,Flutter最佳架构探究

flutter 鸿蒙

背景

Flutter作为最近很火的一个跨平台技术,以其高性能、跨平台的一系列优秀特性成功吸引了很多开发者和组织的青睐,但是由于其不同于传统Android或iOS开发的Widget机制,使得视图的代码往往冗长、不够简洁,解决这种困境的方法就是在开发中合理地运用合适的架构模式,使得程序的视图与数据分离,这样视图层的代码只用专心进行视图的描述和操作即可,不涉及过多复杂的数据操作,这样就可以使视图层的代码达到简洁。

由于Flutter目前没有官方推荐的项目架构,而且笔者也未遇到大家都说好用的架构模式,故此,笔者基于MVP的架构,设计了一套我个人比较青睐的架构模式,本文将详细介绍,希望可以和大家一起沟通、探索,力争衍生出一套适合Flutter的架构模式,从而大大提高生产力,如果文中有什么地方大家觉得设计的不合理的,大可提出,我们一起讨论。

从实例看模式

本文将基于一个经典的登录/注册需求展开描述,将登录/注册的界面与逻辑分离,以求达到解耦,我们首先想想,对于一个注册/登录需求,按照传统MVP的思想,应该如何将其视图与逻辑分离,大致的流程应该是这样的:

IView、IPresenter、IModel三个接口分别是View、Presenter、Model类应该实现(Implements)的接口

View类中持有IPresenter类的实例,记做IPresenter(实际上是Presenter类的实例,因为Presenter类实现了IPresenter接口),当View中的登录按钮被点击时,调用iPresenter对象的登录方法

Presenter类中持有IView和IModel类的实例,记做iView和iModel(实际上是View类和Model类的实例,因为View类和Model类分别实现了IView接口和IModel接口),当Presenter的登录方法被调用时,调用iModel对象的登录方法

Model类持有IPresenter的实例,记做IPresenter(实际上是Presenter类的实例,因为Presenter类实现了IPresenter接口),Model类的登录方法被调用后,进行网络操作,发起登录请求,获取登录的结果(成功或失败),并调用iPresenter对象的方法将结果回调给Presenter层

Presenter接收到Model的回调之后调用iView对象的回调方法,将结果继续回调给View层进而实现视图更新,整个操作完成

总结一下,IView、IPresenter、IModel三个接口分别应该包含的方法如下:

IView:登录/注册操作、结果回调操作

IPresenter:登录/注册操作、结果回调操作

IModel:登录/注册操作

可以看到,IView、IPresenter、IModel三个接口都具有登录/注册操作,而IView、IPresenter都具有结果回调操作,这样在定义接口的时候,登录/注册操作的声明会被写3遍、结果回调操作的声明会被写2遍,代码上会出现臃肿和冗余。所以我对此进行了改进,改进示意图如下:

bf16c137ac70211da37f8a3cc2edfe8f.png

将登录/注册操作这类M、V、P都应该具有的操作抽取到IFunction这个接口中,然后让IView、IPresenter、IModel这三个接口实现(implements)IFunction这个接口,将结果回调操作抽取到ICallBack这个接口中,让IView、IPresenter这两个接口实现(implements)这个接口,然后,让View实现(implements)IView接口,让Presenter实现(Implements)IPresenter这个接口,让Model实现(Implements)IModel这个接口,这样,一个登录操作的完成流程是这样的:

View类持有IPresenter类的实例,记做iPresenter(实际上是Presenter类的实例,因为Presenter类实现了IPresenter接口),当View中的登录按钮被点击时,调用iPresenter对象的登录方法

Presenter类中持有IView和IModel类的对象,记做iView和iModel(实际上是View类和Model类的实例,因为View类和Model类分别实现了IView接口和IModel接口),当Presenter类的登录方法被调用时,调用iModel对象的登录方法

Model类持有ICallBack类的实例,记做iCallBack(实际上是Presenter类的实例,因为Presenter类实现了IPresenter接口,而IPresenter接口实现了ICallBack接口),Model类的登录方法被调用后,进行网络操作,发起登录请求,获取登录的结果(成功或失败),并调用iCallBack对象的回调方法将结果回调给iPresenter

Presenter接收到Model的回调之后调用iView对象的实例,将结果继续回调给View层进而实现视图更新,整个操作完成

这样,我们使用IFunction和ICallBack分别将登录/注册操作和结果回调操作进行封装,然后使IView、IPresenter、IModel分别实现自己应该具有的功能,最后让View、Presenter、Model分别实现IView、IPresenter、IModel接口,一步一步实现了视图与数据的解耦。

代码实现

以上是理论分析部分,落实在代码中,我来大家一步一步地实现:

首先定义我们所说的登录/注册操作对应的LoginInterface接口:

enum RequestType { LOGIN, SIGNUP }

class LoginInterface {

//这里通过RequestType区分当前操作是登录操作还是注册操作

logInOrSignUp(String userName, String passWord, RequestType requestType) {}

}

然后来定义回调方法对应的ILoginCallBack接口:

class ILoginCallBack {

//登录/注册成功

logInOrSignUpSuccess(User user, String describe) {}

//登录/注册失败

logInOrSignUpFailed(String describe) {}

}

然后来定义IView接口,因为View应该有登录/注册、回调两个功能,因此应该让IView接口实现LoginInterface、ILoginCallBack两个接口:

class ILoginPage implements LoginInterface,ILoginCallBack {

showProsess(bool show) {}

@override

logInOrSignUp(String userName, String passWord, RequestType requestType) {

// TODO: implement logInOrSignUp

return null;

}

@override

logInOrSignUpFailed(String describe) {

// TODO: implement logInOrSignUpFailed

return null;

}

@override

logInOrSignUpSuccess(User user, String describe) {

// TODO: implement logInOrSignUpSuccess

return null;

}

}

注意,这里只是定义接口,所以方法不用实现。

定义IPresenter接口,由于Presenter应该有登录/注册、回调两个功能,因此应该让IView接口实现LoginInterface、ILoginCallBack两个接口:

class ILoginPagePresenter implements LoginInterface, ILoginCallBack {

@override

logInOrSignUp(String userName, String passWord, RequestType requestType) {

// TODO: implement logInOrSignUp

return null;

}

@override

logInOrSignUpFailed(String describe) {

// TODO: implement logInOrSignUpFailed

return null;

}

@override

logInOrSignUpSuccess(User user, String describe) {

// TODO: implement logInOrSignUpSuccess

return null;

}

}

最后定义IModel接口,其只需要登录/注册一个功能即可,因此让IModel接口实现Logininterface这一个接口即可:

class ILoginModel implements LoginInterface {

@override

logInOrSignUp(String userName, String passWord, RequestType requestType) {

// TODO: implement logInOrSignUp

return null;

}

}

然后我们来实现View、Presenter、Model三个类:

View:

class _LoginState extends State implements ILoginPage{

ILoginPagePresenter iLoginPagePresenter;

@override

void initState() {

iLoginPagePresenter = LogInPresenter(this);

super.initState();

}

@override

logInOrSignUp(String userName, String passWord, RequestType requestType) {

iLoginPagePresenter.logInOrSignUp(userName, passWord, requestType);

}

@override

logInOrSignUpFailed(String describe) {

// TODO: 登录/注册失败,更新视图

}

@override

logInOrSignUpSuccess(User user, String describe) {

// TODO: 登录/注册成功,更新视图

}

}

Presenter:

class LogInPresenter implements ILoginPagePresenter {

ILoginPage _iLoginPage;

ILoginModel _iLoginModel;

LogInPresenter(this._iLoginPage) {

_iLoginModel = LoginModel(this);

}

@override

logInOrSignUp(String userName, String passWord, RequestType requestType) {

_iLoginModel.logInOrSignUp(userName, passWord, requestType);

}

@override

logInOrSignUpFailed(String describe) {

_iLoginPage.logInOrSignUpFailed(describe);

}

@override

logInOrSignUpSuccess(User user, String describe) {

_iLoginPage.logInOrSignUpSuccess(user, describe);

}

}

Model:

class LoginModel implements ILoginModel {

ILoginCallBack _iLoginCallBack;

LoginModel(this._iLoginCallBack);

@override

logInOrSignUp(String userName, String passWord, RequestType requestType) {

// TODO: 发起网络操作进行登录/注册

_iLoginCallBack.logInOrSignUpSuccess(user, describe);

}

}

至此我们就对登录/注册这个功能完成了架构改造,可以发现,经过架构改造之后,整个项目的条理非常清晰,避免了视图层代码太过冗余的痛点,利于维护、测试。

总结

本文针对Flutter中的登录/注册场景进行了架构改造,整个逻辑是基于MVP,解决了MVP中接口冗余的痛点,当然本架构还存在很多问题,欢迎大家及时指出,一起交流。

作者:ai-exception

来源:CSDN

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/257299
推荐阅读
相关标签
  

闽ICP备14008679号