zoukankan      html  css  js  c++  java
  • MVP架构在xamarin android中的简单使用

    好几个月没写文章了,使用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() + "
    公司地址:" + model.comaddress + "
    公司名称:" + model.comname + "
    网备案号:" + model.id + "
    域名" + model.sitedomain + "
    简称:" + 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,都只是一种思考问题的思维,其目的还是要解决变成过程中高内聚、低耦合、可维护、易测试。

  • 相关阅读:
    php多态
    ssl certificate problem: self signed certificate in certificate chain
    test plugin
    open specific port on ubuntu
    junit vs testng
    jersey rest service
    toast master
    use curl to test java webservice
    update folder access
    elk
  • 原文地址:https://www.cnblogs.com/zhangmumu/p/9053969.html
Copyright © 2011-2022 走看看