Android MVC模式和回调

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:layout_marginTop="5dp"
        android:gravity="center"
        android:textSize="16sp" />

</LinearLayout>

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

public interface OnNewsListener {
    void onSuccess(News news);
    void onError();
}
1
2
3
4
这个接口里面只给了见单的2个操作成功失败。

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

public interface NewsModel {
    void getWeather(String name, OnNewsListener mlistener);
}
1
2
3
第四步: 就是我们的逻辑处理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();
    }
}

回调

回调的就是把方法的定义和功能导入实现分开的一种机制,目的是为了解耦,本质是基于观察者设计模式,观察者设计模式的简化版。回调的作用:一是传递数据。而是保持数据的同步更新。常用的两种形式:一种是使用内部类的形式得到子接口对象。另一种是直接实现定义的接口。

Java允许我们调用接口的方法,但是有一个前提,就是编译的时候接口的对象必须是一个具体的类,并且这个类实现了接口。当我们调用接口的方法的时候,接口的具体子类中的具体方法会被调用,这就是回调。嗯,我说什么鬼?还是上代码吧。

public interface A {
    void printClassName();
}
public class B implements A {
    public void printClassName() {
        System.out.println("This is class B!");
    }
}
public static void main(String[] args) {
        A a = new B();
        a.printClassName();
}

输出的结果如下:

从上面的代码可以看到,我们在主函数中定义了接口A,也调用了接口A的方法,但是要注意,我们实例化的时候其实new的是一个实现了A接口的具体类,我们调用A中的printClassName方法的时候Java就会去回调B中的该方法。这样做的优点是什么?就是我们在调用的时候,可以完全不管A的子类是如何实现A中的方法的,只需要调用这个方法即可,怎么实现,我们不管,那是子类的事情了,这样其实是解耦的一种很好的方法,如果我们要修改为别的类,只需要把new后面的子类改掉就好。

猜你喜欢

转载自blog.csdn.net/gxflh/article/details/87858341