好几个月没写文章了, 使用 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 将 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 的缺点是:
代码更加复杂, 代码量增加.
实践是检验真理的唯一标准, 下面通过一个简单的例子获取天气预报信息看看, 如何在 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 如下:
- public class GongAnPresenter
- {
- private IGongAnView view;
- public GongAnPresenter(IGongAnView view)
- {
- this.view = view;
- }
- public async void showResult(string sitedomain)
- {
- var result = await SearchGongAn.getGonganDetail(sitedomain);
- if (result != null && result.status == 200)
- view.getServiceGongAnSuccess(result.data);
- else if (result == null)
- {
- view.getServiceGonganFail("请求失败");
- }
- else
- {
- view.getServiceGonganFail("没有备案: status:"+result.status);
- }
- }
- }
新建 Views 文件夹 ,IGongAnView.cs 接口 如下
- public interface IGongAnView
- {
- void getServiceGongAnSuccess(Data model);
- void getServiceGonganFail(string error);
- }
新建 Model 文件夹, SearchGongAn.cs 如下:
- public class SearchGongAn
- {
- private static string url= "https://www.sojson.com/api/gongan/{0}";
- public static async System.Threading.Tasks.Task<GongAnModel> getGonganDetail(string city)
- {
- try
- {
- HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(string.Format(url, city));
- request.Method = "get";
- HttpWebResponse response = (HttpWebResponse)request.GetResponse();
- Stream responseStream = response.GetResponseStream();
- StreamReader streamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
- string result = await streamReader.ReadToEndAsync();
- GongAnModel model = JsonConvert.DeserializeObject<GongAnModel>(result);
- streamReader.Close();
- responseStream.Close();
- return model;
- }
- catch (Exception ex)
- {
- Log.Info("ex",ex.ToString());
- return null;
- }
- }
- }
- Mainactivity.cs
- [Activity(Label = "PeresenterForXamarinAndroid", MainLauncher = true, Icon = "@drawable/icon")]
- public class MainActivity : Activity,IGongAnView,View.IOnClickListener
- {
- TextView txt_result;
- Button btn_search;
- EditText btn_sitedomain;
- GongAnPresenter presenter;
- ProgressDialog progressDialog;
- protected override void OnCreate(Bundle bundle)
- {
- base.OnCreate(bundle);
- SetContentView(Resource.Layout.Main);
- txt_result = FindViewById<TextView>(Resource.Id.txt_result);
- btn_search = FindViewById<Button>(Resource.Id.btn_search);
- btn_sitedomain = FindViewById<EditText>(Resource.Id.btn_sitedomain);
- presenter = new Peresenter.GongAnPresenter(this);
- progressDialog = new ProgressDialog(this);
- progressDialog.SetTitle("搜索公网备案");
- progressDialog.SetMessage("正在搜索, 请稍后.....");
- btn_search.SetOnClickListener(this);
- }
- public void OnClick(View v)
- {
- if (v.Id == Resource.Id.btn_search)
- {
- string sitedomain = btn_sitedomain.Text;
- string pattern = @"^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$";
- Regex reg = new Regex(pattern);
- if (string.IsNullOrEmpty(sitedomain))
- {
- Toast.MakeText(this, "请输入域名", ToastLength.Short).Show();
- }
- else if (reg.IsMatch(sitedomain))
- {
- progressDialog.Show();
- presenter.showResult(sitedomain);
- }
- else
- {
- Toast.MakeText(this, "域名错误, 请重新输入", ToastLength.Short).Show();
- }
- }
- }
- public void getServiceGongAnSuccess(Data model)
- {
- progressDialog.Hide();
- txt_result.Text = "工信部更新日期:" + model.cdate.ToShortDateString() + "\n 公司地址:" + model.comaddress + "\n 公司名称:" + model.comname + "\n 网备案号:" + model.id + "\n 域名" + model.sitedomain + "\n 简称:" + model.sitename;
- }
- public void getServiceGonganFail(string error)
- {
- progressDialog.Hide();
- txt_result.Text = "查询失败";
- Toast.MakeText(this,error,ToastLength.Short).Show();
- }
- }
总结
纸上得来终觉浅, 绝知此事要躬行. 只要不断实践, 丰富项目经验, 架构模式在初学者前期并不是那么重要. android 开发无外乎就三种架构 MVC,MVP,MVVM.MVP 模式简单易用非常容易上手, Presenter 隔断了 View 和 Model 的联系, 作为两者沟通的桥梁, 在 Activityhe fragment 中你的代码就不会变得臃肿, 杂乱了.
引用一句我非常喜欢的话:
架构只是一种思维模式, 不管是 MVC,MVP 还是 MVVM, 都只是一种思考问题的思维, 其目的还是要解决变成过程中高内聚, 低耦合, 可维护, 易测试.
来源: https://www.cnblogs.com/zhangmumu/p/9053969.html