您的位置:首页 > 移动开发 > Android开发

Android 设计模式之MVC,从一个实例中来理解MVC

2018-01-16 11:41 736 查看

前言

已经有几天没有写过帖子了,主要前一段时间在忙公司的项目,现在闲下来想看一下其他的东西,然后从公司的iOS大神那里了解到了苹果的设计模式是MVC,于是想着自己也来写一下Android这边的MVC。然后这里我就不多扯皮了,Mhahahahha…

名言

对于攀登者来说,失掉往昔的足迹并不可惜,迷失了继续前时的方向却很危险。

MVC的介绍

MVC是Model-View-Controller的简称

Model:模型层,负责处理数据的加载或者存储

View:视图层,负责界面数据的展示,与用户进行交互

Controller:控制器层,负责逻辑业务的处理

那我们为什么要用到MVC模式呢?

1、耦合性低。降低了代码的耦合性,利用MVC框架使得View(视图)层和Model(模型)层可以很好的分离,这样就达到了解耦的目的,所以耦合性低,减少模块代码之间的相互影响。

2、模块区域分明,方便开发人员的维护。

接下来我们就看一个例子,从例子中来理解MVC设计模式

老规矩我们先来看看例子的效果图。



先来解释一下这个例子,我这个例子是请求网络获取新闻头条的一下标题等内容(接口我是在聚合数据上面找的免费的),然后代码中我会体现出怎么把Model和view和Controller分离开来。

首先来看看整体的项目架构。



然后来解释一下

News—>新闻的实体类

MyService—>我这里请求网络用的是Retrofit,所以这里有个请求的接口

NewsModel—>这个接口是C层和M层用来交互的

NewsModelImpl—>这个是用来Model层用来进行请求网络的处理

OnNewsListener—>这个是Model逻辑处理完成后通知View层进行改变的

第一步:首先我们来看看xml。很简单的一个布局一个输入一个按钮,几个textview

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>

<EditText
android:id="@+id/edit"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_margin="16dp"
android:hint="请输入新闻种类" />

<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:text="查询" />

<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="44dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="5dp"
android:gravity="center"
android:textSize="16sp" />

<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="44dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="5dp"
android:gravity="center"
android:textSize="16sp" />

<TextView
android:id="@+id/category"
android:layout_width="match_parent"
android:layout_height="44dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="5dp"
android:gravity="center"
android:textSize="16sp" />

<TextView
android:id="@+id/author_name"
android:layout_width="match_parent"
android:layout_height="44dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:la
4000
yout_marginTop="5dp"
android:gravity="center"
android:textSize="16sp" />

</LinearLayout>


第二步:我们说了我们要把model和view分开,但是需要联系,model处理完成了以后需要告诉view层我做完了请你展示。所以他们直接是要用联系的那就是OnNewsListener

public interface OnNewsListener {
void onSuccess(News news);
void onError();
}


这个接口里面只给了见单的2个操作成功失败。

第三步: 我们知道用户通过Controller告诉model应该干什么说以,他们之间的联系就是NewsModel

public interface NewsModel {
void getWeather(String name, OnNewsListener mlistener);
}


第四步: 就是我们的逻辑处理NewsModelImpl进行网络请求

public class NewsModelImpl implements NewsModel {
private final String baseUrl = "http://v.juhe.cn";
private final String key = "这个地方就写你在聚合数据上面申请的今日头条的KEY";
@Override
public void getWeather(String name, final OnNewsListener mlistener) {
OkHttpClient.Builder client = new OkHttpClient.Builder();
Retrofit retrofit = new Retrofit.Builder()
.client(client.build())
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
MyService service = retrofit.create(MyService.class);
service.getNews(key,name).enqueue(new Callback<News>() {
@Override
public void onResponse(Call<News> call, Response<News> response) {
News news = response.body();
if (news.getReason().equals("成功的返回")) {
Log.e("news", "成功");
mlistener.onSuccess(news);
} else {
Log.e("news", "失败");
mlistener.onError();
}
}
@Override
public void onFailure(Call<News> call, Throwable t) {
t.getStackTrace();
mlistener.onError();
}
});
}
}


请求成功我们就通过OnNewsListener告诉view可以开始变了

第五步: 我们看看MainActivity

public class MainActivity extends AppCompatActivity implements OnNewsListener, View.OnClickListener {
private EditText editText = null;
private Button button = null;
private TextView title, date, category, author_name = null;

private NewsModelImpl weatherModel = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
weatherModel = new NewsModelImpl();
initView();
}

public void initView() {
editText = (EditText) findViewById(R.id.edit);
button = (Button) findViewById(R.id.button);
title = (TextView) findViewById(R.id.title);
date = (TextView) findViewById(R.id.date);
category = (TextView) findViewById(R.id.category);
author_name = (TextView) findViewById(R.id.author_name);

button.setOnClickListener(this);
}

//设置数据
public void setView(News news) {
title.setText(news.getResult().getData().get(1).getTitle());
date.setText(news.getResult().getData().get(1).getDate());
category.setText(news.getResult().getData().get(1).getCategory());
author_name.setText(news.getResult().getData().get(1).getAuthor_name());
}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
String name = editText.getText().toString();
if (!name.equals("")) {
weatherModel.getWeather(name, this);
} else {
Toast.makeText(this, "输入的新闻标题不能为空", Toast.LENGTH_SHORT).show();
}
break;
}
}

@Override
public void onSuccess(News news) {
setView(news);
}

@Override
public void onError() {
Toast.makeText(this, "出错了哦!", Toast.LENGTH_SHORT).show();
}
}


这样就大功告成了!

然后看到这突然发现activity不仅仅座位了view层,还作为了Controller,其实做过电商类的都应该知道按照道理来说我们这个地方应该把Controller单独的提出来写,因为在Android中如果用xml作为view层的话,显得就有些苍白无力,所以activity作为了view层。但在iOS中就不会存在这个问题,所以我个人觉得MVP的模式更加适合Android。

写的有不好的地方~~~~请多指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息