MVP架构在xamarin android中的简单使用

简介: 好几个月没写文章了,使用xamarin android也快接近两年,还有一个月职业生涯就到两个年了,从刚出来啥也不会了,到现在回头看这个项目,真jb操蛋(真辛苦了实施的人了,无数次吐槽怎么这么丑),怪自己太年轻了,还好是给指定行业的人使用。

好几个月没写文章了,使用xamarin android也快接近两年,还有一个月职业生涯就到两个年了,从刚出来啥也不会了,到现在回头看这个项目,真jb操蛋(真辛苦了实施的人了,无数次吐槽怎么这么丑),怪自己太年轻了,还好是给指定行业的人使用。 重新学习思考之后,再看自己在项目中的某些实现的代码,的确不尽人意,甚至想骂自己。

项目经常改,改来该去,代码一直增加,一个fragment也没什么功能,接近1000行的代码,用region括起来,开看起来还挺整齐的,找的时候就凉了。究其原因,没有一种模式,所有的逻辑全写在controller(fragment和activity里面),当然不管了解不了解什么框架模式、设计模式。最主要、最基本的还是实现功能和良好的用户体验,一些小的项目,不需要频繁修改需求甚至不需要MVP、MVC等模式来设计,那样反而有点刻意设计,代码复杂臃肿。关于android中mvp架构的介绍文章非常丰富,这里我只是做一个学习的记录,温故而知新。

程序的思想都是通用的,搞.net对于mvc框架应该是非常熟悉,webform用的目前应该不是很多。先说说android中 MVC,mvc分为三部分 :视图(View用户界面)、Controller(fragmnet、activity控制器业务逻辑)、Model(数据存取); 
这里写图片描述 
Model:负责数据的处理、请求网络数据、读取本地数据、检验等 
View:UI操作,控件的实际处理,更新Model层的数据,负责用户请求通知Controller 
Controller:Activity和Fragment,初始化各种控件,加载数据、逻辑的处理,职责比较多。

什么是MVP

mvp是从经典的mvc模式演变而来的,但是mvc模式中的View是可以直接访问model的,两者的重大的区别在于:mvp中presenter隔断model与view的通信,view与model的交互通过presenter来实现。

mvp将controller改成了peresenter提出者,也改变了通信的方向,是一个MVC的改良版,MVP的结构如下: 
这里写图片描述
Model:存取数据,网络数据、SharedPreferences、sqlite等数据的存取 
Presenter:订阅,负责View和Model的交互,隔断View层和Model层的交互。调用View中的相应方法展示数据 
View:Fragment、Activity、ViewGroup 这一层,处理用户的交互和事件,并触发Presenter中的相应操作 
mvp的优点是: 
1.view与model不发生任何交互,view层不能持有Model层的引用,不能直接去更新Model层,必须通过Presenter层,Presenter层中也不能直接操作View及相关的UI控件,必须通过View层的引用来操作。 
2.便于测试,维护性提高,代码结构更加清晰,可以明显看到Activity和 
3.View与Model分离使工程的整体架构和代码结构非常清晰(不再是所有的业务和逻辑都糅合在Activity、Fragment里了),易于理解和上手。 
mvp的缺点是: 
代码更加复杂,代码量增加。 在使用中我也发现了很多弊端,每个Activity、Fragment都需要划分一套MVP,这无形之中增加很多类和接口,每次通信都需要繁琐的接口传递信息,这些确定也演化了许多版本的MVP,更多详细可以参考:传统MVP用在项目中是真的方便还是累赘? 
实践是检验真理的唯一标准,下面通过一个简单的例子获取天气预报信息看看,如何在xamarin android项目如何使用MVP架构吧

使用mvp架构实现查询公网备案的例子

天气预报的接口:https://www.sojson.com/api/gongan/域名,根据域名查询备案信息 
返回的格式是json. 
如果你想更深入地了解mvp架构,可以参看一下google官方MVP框架源码解析之TODO-MVP 
https://github.com/googlesamples/android-architecture/tree/todo-mvp/ 
效果图如下: 
 
项目的结构如下: 
这里写图片描述 
新建peresenter文件夹,GongAnPresenter.cs 如下:

 1     public class GongAnPresenter
 2     {
 3         private IGongAnView view;
 4         public GongAnPresenter(IGongAnView view)
 5         {
 6             this.view = view;
 7         }
 8         public async void showResult(string sitedomain)
 9         {
10             var result = await SearchGongAn.getGonganDetail(sitedomain);
11             if (result != null && result.status == 200)
12                 view.getServiceGongAnSuccess(result.data);
13             else if (result == null)
14             {
15                 view.getServiceGonganFail("请求失败");
16             }
17             else
18             {
19                 view.getServiceGonganFail("没有备案:status:"+result.status);
20             }
21         }
22     }
 

  新建Views文件夹 ,IGongAnView.cs 接口 如下

    public interface IGongAnView
    {
        void getServiceGongAnSuccess(Data model);
        void getServiceGonganFail(string  error);
    }

新建Model文件夹,SearchGongAn.cs如下:

 1     public class SearchGongAn
 2     {
 3        private  static string  url= "https://www.sojson.com/api/gongan/{0}";
 4         public static async System.Threading.Tasks.Task<GongAnModel> getGonganDetail(string city)
 5         {
 6             try
 7             {
 8                 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(string.Format(url, city));
 9                 request.Method = "get";
10                 HttpWebResponse response = (HttpWebResponse)request.GetResponse();
11                 Stream responseStream = response.GetResponseStream();
12                 StreamReader streamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
13                 string result = await streamReader.ReadToEndAsync();
14                 GongAnModel model = JsonConvert.DeserializeObject<GongAnModel>(result);
15                 streamReader.Close();
16                 responseStream.Close();
17                 return model;
18             }
19             catch (Exception ex)
20             {
21                 Log.Info("ex",ex.ToString());
22                 return null;
23             }
24         }
25     }

 

 

Mainactivity.cs

 1  [Activity(Label = "PeresenterForXamarinAndroid", MainLauncher = true, Icon = "@drawable/icon")]
 2     public class MainActivity : Activity,IGongAnView,View.IOnClickListener
 3     {
 4         TextView txt_result;
 5         Button btn_search;
 6         EditText btn_sitedomain;
 7         GongAnPresenter presenter;
 8         ProgressDialog progressDialog;
 9         protected override void OnCreate(Bundle bundle)
10         {
11             base.OnCreate(bundle);
12             SetContentView(Resource.Layout.Main);
13             txt_result = FindViewById<TextView>(Resource.Id.txt_result);
14             btn_search = FindViewById<Button>(Resource.Id.btn_search);
15             btn_sitedomain = FindViewById<EditText>(Resource.Id.btn_sitedomain);
16             presenter = new Peresenter.GongAnPresenter(this);
17             progressDialog = new ProgressDialog(this);
18             progressDialog.SetTitle("搜索公网备案");
19             progressDialog.SetMessage("正在搜索,请稍后.....");
20             btn_search.SetOnClickListener(this);
21         }
22 
23         public void OnClick(View v)
24         {
25             if (v.Id == Resource.Id.btn_search)
26             {
27                 string sitedomain = btn_sitedomain.Text;
28                 string pattern = @"^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$";
29                 Regex reg = new Regex(pattern);
30                 if (string.IsNullOrEmpty(sitedomain))
31                 {
32                     Toast.MakeText(this, "请输入域名", ToastLength.Short).Show();
33                 }
34                 else if (reg.IsMatch(sitedomain))
35                 {
36                     progressDialog.Show();
37                     presenter.showResult(sitedomain);
38                 }
39                 else
40                 {
41                     Toast.MakeText(this, "域名错误,请重新输入", ToastLength.Short).Show();
42                 }
43             }
44         }
45         public void getServiceGongAnSuccess(Data model)
46         {
47             progressDialog.Hide();
48             txt_result.Text = "工信部更新日期:" + model.cdate.ToShortDateString() + "\n公司地址:" + model.comaddress + "\n公司名称:" + model.comname + "\n网备案号:" + model.id + "\n域名" + model.sitedomain + "\n简称:" + model.sitename;
49         }
50 
51         public void getServiceGonganFail(string error)
52         {
53             progressDialog.Hide();
54             txt_result.Text = "查询失败";
55             Toast.MakeText(this,error,ToastLength.Short).Show();
56         }
57     }

 

总结

纸上得来终觉浅,绝知此事要躬行。只要不断实践,丰富项目经验,架构模式在初学者前期并不是那么重要。android开发无外乎就三种架构MVC、MVP、MVVM。MVP模式简单易用非常容易上手,Presenter隔断了View和Model的联系,作为两者沟通的桥梁,在Activityhe fragment中你的代码就不会变得臃肿,杂乱了。 
引用一句我非常喜欢的话:

架构只是一种思维模式,不管是MVC、MVP还是MVVM,都只是一种思考问题的思维,其目的还是要解决变成过程中高内聚、低耦合、可维护、易测试。

相关实践学习
基于函数计算快速搭建Hexo博客系统
本场景介绍如何使用阿里云函数计算服务命令行工具快速搭建一个Hexo博客。
目录
相关文章
|
1月前
|
数据库 Android开发 开发者
构建高性能微服务架构:从理论到实践构建高效Android应用:探究Kotlin协程的优势
【2月更文挑战第16天】 在当今快速迭代和竞争激烈的软件市场中,微服务架构以其灵活性、可扩展性和独立部署能力而受到企业的青睐。本文将深入探讨如何构建一个高性能的微服务系统,涵盖从理论基础到具体实现的各个方面。我们将重点讨论服务拆分策略、通信机制、数据一致性以及性能优化等关键主题,为读者提供一个清晰、实用的指南,以便在复杂多变的业务环境中构建和维护健壮的微服务体系结构。 【2月更文挑战第16天】 在移动开发领域,性能优化和流畅的用户体验是至关重要的。随着技术的不断进步,Kotlin作为一种现代编程语言,在Android开发中被广泛采用,尤其是其协程特性为异步编程带来了革命性的改进。本文旨在深入
241 5
|
2天前
|
传感器 Java Android开发
Android HAL深入探索(1): 架构概述
Android HAL深入探索(1): 架构概述
17 1
|
13天前
|
存储 数据库 Android开发
构建高效安卓应用:采用Jetpack架构组件优化用户体验
【4月更文挑战第12天】 在当今快速发展的数字时代,Android 应用程序的流畅性与响应速度对用户满意度至关重要。为提高应用性能并降低维护成本,开发者需寻求先进的技术解决方案。本文将探讨如何利用 Android Jetpack 中的架构组件 — 如 LiveData、ViewModel 和 Room — 来构建高质量的安卓应用。通过具体实施案例分析,我们将展示这些组件如何协同工作以实现数据持久化、界面与逻辑分离,以及确保数据的即时更新,从而优化用户体验并提升应用的可维护性和可测试性。
|
24天前
|
移动开发 前端开发 数据管理
构建高效Android应用:采用MVVM架构与LiveData的全面指南
在移动开发领域,构建一个既快速又可靠的应用对于开发者来说至关重要。随着Android Jetpack组件的推出,MVVM(Model-View-ViewModel)架构和LiveData已成为实现响应式、可测试且易于维护应用的首选解决方案。本文将深入探讨如何在Android应用中实施MVVM模式,以及如何利用LiveData来优化UI组件的数据更新流程,确保用户界面与业务逻辑之间的高度解耦和流畅交互。
18 4
|
3月前
|
设计模式 存储 前端开发
【各种问题处理】MVC、MVP、MVVM 、MVI、VIPER 架构(设计模式)
【1月更文挑战第13天】【各种问题处理】MVC、MVP、MVVM 、MVI、VIPER 架构(设计模式)
|
3月前
|
存储 前端开发 测试技术
Android 官方架构中的 UseCase 该怎么写?
Android 官方架构中的 UseCase 该怎么写?
66 0
|
6月前
|
开发工具 Android开发 iOS开发
使用xamarin开发Android、iOS报错failed to open directory: 系统找不到指定的文件
使用vs2019学习xamarin时,创建新程序。使用模拟器真机等测试都报错如下图错误: ![请在此添加图片描述](https://developer-private-1258344699.cos.ap-guangzhou.myqcloud.com/column/article/5877188/20231030-de8ce5fd.png?x-cos-security-token=r4KyZDEowPT0kGTL0LqE8EnwfN1Nzexadb05dcffed3939ff8d7591c528c01706nvpGSE93QwHpZM8NwhJNTZctNRQa0l3KDhEnqj8P7d8t
63 0
使用xamarin开发Android、iOS报错failed to open directory: 系统找不到指定的文件
|
6月前
|
设计模式 网络协议 Java
《移动互联网技术》 第十章 系统与通信: 掌握Android系统的分层架构设计思想和基于组件的设计模式
《移动互联网技术》 第十章 系统与通信: 掌握Android系统的分层架构设计思想和基于组件的设计模式
65 0
|
8月前
|
API Android开发 Kotlin
安卓MVI架构真的来了?动手试着封装吧(三)下
安卓MVI架构真的来了?动手试着封装吧(三)
82 0
|
8月前
|
Android开发 开发者 Kotlin
安卓MVI架构真的来了?动手试着封装吧(三)上
安卓MVI架构真的来了?动手试着封装吧(三)
120 0