我今天给大家带来了一个简单的MVP小案例,如有错误之处,还请多多指教评论,共同进步。这是效果图,虽然有点丑,但不要在意这些细节,我们的目的是成功的去了解MVP这个模式,而不是去做布局的。
效果图:
在这里插入图片描述
第一步我们先加一下权限:
<uses-permission android:name="android.permission.INTERNET" />
第二步我们写Http工具类:
package com.example.app7.utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class HttpUtils {
public static String get(String urlString) throws Exception {
URL url=new URL(urlString);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
String str=getStr(inputStream);
return str;
}
private static String getStr(InputStream inputStream) throws IOException {
BufferedReader read=new BufferedReader(new InputStreamReader(inputStream));
StringBuffer sb=new StringBuffer();
String con="";
while ((con=read.readLine())!=null)
{
sb.append(con);
}
return sb.toString();
}
}
**第三步:**抽取BaseActivity类:
package com.example.app7.base;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
public abstract class BaseActivity extends AppCompatActivity implements View.OnClickListener{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//重写后方法执行的顺序
init();
}
//加载布局
protected abstract int getLayout();
//初始化组件
protected abstract void initViews();
//注册监听
protected abstract void setOnclik();
//逻辑操作
protected abstract void processLogic();
void init()
{
if(getLayout()!=0)
{
setContentView(getLayout());
initViews();
setOnclik();
processLogic();
}
else
{
//抛出非法状态异常
throw new IllegalStateException("请加载布局文件");
}
};
}
**第四步:**写一个Model层,在里面新建一个model接口
package com.example.app7.model;
import com.example.app7.callback.MyCallBack;
//定义一个规范(一个定义语言)
public interface Model {
第一个参数是接口地址,第二个参数是后期做活数据,拼接接口的,第三个参数是回调保存的数据
void getData(String url,String params,MyCallBack callBack);
}
**第五步:**写回调保存的接口
package com.example.app7.callback;
public interface MyCallBack {
//请求成功保存数据
void success(String data);
//请求数据失败
void error(String error);
}
**第六步:**在model新建一个类,实现model的接口:
package com.example.app7.model;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import com.example.app7.callback.MyCallBack;
import com.example.app7.utils.HttpUtils;
public class ModelImpl implements Model {
//回调保存数据的接口
private MyCallBack callBack;
private Handler mHandler=new Handler()
{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//接收子线程的传递过来的值,进行判断
if(msg.what==0)
{
//定义一个String,把子线程的值赋值给data
String data= (String) msg.obj;
//当请求数据不为空时
if(callBack!=null)
{
callBack.success(data);
}
}
}
};
@Override
public void getData(final String url, String params, final MyCallBack callBack) {
this.callBack=callBack;
//子线程
new Thread(new Runnable() {
@Override
public void run() {
try {
//通过工具类获取数据
String data =HttpUtils.get(url);
//更新主线程
mHandler.sendMessage(mHandler.obtainMessage(0,data));
} catch (Exception e) {
//把其他线程的代码放到主线程里面操作的
Looper.prepare();
callBack.error("异常");
//开始执行
Looper.loop();
}
}
}).start();
}
}
**第七步:**抽取一个View接口
package com.example.app7.view;
public interface IVew {
//没加载数据之前显示一个ProgressBar
void showLoging();
//成功的时候通过Presenter层得到数据
void getData(String data);
//失败的时候通过Presenter得到失败的信息
void getError(String error);
//加载完成,关闭ProgressBar
void onComple();
}
**第八步:**抽取一个Presenter接口,P层用来管理M层和V层
package com.example.app7.presenter;
public interface IPresenter {
//第一个参数是接口地址,第二个参数是一个备用参数
void startRequest(String url,String params);
}
**第九步:**实现Present接口
package com.example.app7.presenter;
import com.example.app7.MainActivity;
import com.example.app7.callback.MyCallBack;
import com.example.app7.model.ModelImpl;
import com.example.app7.view.IVew;
//通过P层来管理M层和V层
public class PresenterImpl implements IPresenter{
private ModelImpl modelimpl;
private IVew iVew;
//构造方法
public PresenterImpl(IVew iVew) {
//得到V层和M层的对象,V层对象在主页面时传过来
this.iVew = iVew;
modelimpl = new ModelImpl();
}
@Override
public void startRequest(String url, String params) {
iVew.showLoging();
modelimpl.getData(url, params, new MyCallBack() {
@Override
public void success(String data) {
//关闭ProgressBar
iVew.onComple();
//获取数据
iVew.getData(data);
}
@Override
public void error(String error) {
iVew.onComple();
iVew.getError(error);
}
});
}
//一个优化,为了防止内存溢出
public void onDetach()
{
if(modelimpl!=null)
{
modelimpl=null;
}
if(iVew!=null)
{
iVew=null;
}
}
}
**第十步:**在MainActivity进行具体操作
package com.example.app7;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.example.app7.base.BaseActivity;
import com.example.app7.presenter.PresenterImpl;
import com.example.app7.view.IVew;
public class MainActivity extends BaseActivity implements IVew {
private Button Send_Btn;
private TextView Get_Text;
private ProgressBar progressBar;
private PresenterImpl presenter;
private String mUrl = "http://api.expoon.com/AppNews/getNewsList/type/1/p/1";
@Override
protected int getLayout() {
return R.layout.activity_main;
}
@Override
protected void initViews() {
Send_Btn=findViewById(R.id.Send_Btn);
Get_Text=findViewById(R.id.Get_Text);
progressBar=findViewById(R.id.progress_bar);
}
@Override
protected void setOnclik() {
//因为在BaseActivity里实现了View的点击事件,所以继承BaseActivity这个类就不用重新实现了
Send_Btn.setOnClickListener(this);
}
@Override
protected void processLogic() {
//得到PresenterImpl的对象,并把View对象传给PresenterImpl类
presenter=new PresenterImpl(this);
}
@Override
public void showLoging() {
//设置ProgressBar为可见的状态
progressBar.setVisibility(View.VISIBLE);
}
@Override
public void getData(String data) {
//给TextView赋值
Get_Text.setText(data+"");
}
@Override
public void getError(String error) {
Toast.makeText(this,error,Toast.LENGTH_SHORT).show();
}
@Override
public void onComple() {
//当数据加载成功的时候把ProgressBar设置为不可见且不占用任何位置
progressBar.setVisibility(View.GONE);
}
//一个优化,为了防止内存溢出
@Override
protected void onDestroy() {
super.onDestroy();
if(presenter!=null)
{
presenter.onDetach();
}
}
@Override
public void onClick(View v) {
switch (v.getId())
{
case R.id.Send_Btn:
调用presenter接口的方法 ,请求数据
presenter.startRequest(mUrl,null);
break;
}
}
}
MVC和MVP最大的区别在于MVC他的Model层是直接和View交互的,这无疑增加了界面的代码量,而MVP的是把Model层和View层彻底分离,而界面上几乎只加载生命周期的方法和点击事件。