菜鸡豪一直以来写代码都非常的混乱,写到哪里想到哪里,发现差什么就写什么,所以整个项目写下来发现代码的重用非常的严重,所以我觉得学习一个框架,改善代码风格显得迫在眉睫了,就此我开始学习MVP模式。
MVP模式整体就是分为M、V、P三个部分,M——model(模型),V——view(视图),P——presenter(主持人)。
model:主要负责数据部分,比如网络请求,存储数据之类与数据相关的操作。
view:主要负责ui的,例如用户交互、数据的展示之类纯ui操作。
presenter:这是MVP模式的特色部分,也是很核心的部分,连接view和model。
我们注意到以前的代码会发现只要model里面数据发生改变的时候就会让view的ui发生改变,因为以前我们大多数的时候是把调用model我的操作直接写在view里面,这样就会导致view和model的耦合度高到爆炸,感觉就像连体的一样,而在MVP中多了一个presenter这样的中间人负责调动view和model,这样view和model并不是直接连接的,而是通过presenter间接连接,view只负责接受数据进行展示,view也变得没有以前那么臃肿,而且以前在view中进行异步操作,activity不能被回收。
关说不练假把式,菜鸡豪写一个小demo来入门MVP模式——聊天机器人
1.我们先写view层
view层主要负责数据的显示,以及与用户交互,比如机器人的回应和用户发出的话语,都需要显示在屏幕上,以及在用户点击发送的时候进行presenter的调用,我们需要写两个方法给presenter更新界面的操作
public interface IChatView {
void clearEdit();
void updateUI(List<String> text,List<Integer> text_type);
}
而在demo中Mainactivity就是主要的view
public class MainActivity extends AppCompatActivity implements IChatView ,View.OnClickListener{
EditText editText;
RecyclerView recyclerView;
CardView cardView;
Madapter madapter;
List<String> text=new ArrayList<>();
List<Integer> text_type=new ArrayList<>();
IPresenter iPresenter;
private String TAG="main";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
cardView=findViewById(R.id.send);
editText=findViewById(R.id.edit);
recyclerView=findViewById(R.id.recyclerview);
text.add("阿毛大宝贝我们开始聊天吧");
text_type.add(0);
iPresenter=new IPresenter(this,text,text_type);
madapter=new Madapter(this,text,text_type);
LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this);
recyclerView.setAdapter(madapter);
recyclerView.setLayoutManager(linearLayoutManager);
cardView.setOnClickListener(this);
}
@Override
public void clearEdit() {
editText.setText("");
}
@Override
public void updateUI(final List<String> text, final List<Integer> text_type) {
runOnUiThread(new Runnable() {
@Override
public void run() {
madapter.setDateList(text,text_type);
madapter.notifyDataSetChanged();
}
});
}
@Override
public void onClick(View v) {
if(v==cardView)
{
String userText=editText.getText().toString();
if(userText!=null)
{
iPresenter.send(userText);
}
}
}
}
可以看到主要的就是ui的初始化,对两个方法进行重写,和发送的点击逻辑,我这里是用的cardview写的一个假按钮。
clearEdit方法就是发送后清空输入框,updateUI就是进行UI的更新,点击逻辑里面就是调用presenter里面的发送方法
2.接下来我们就开始写presenter层
presenter主要的方法就是将用户输入的话发送给model层进行网络请求,然后得到model回调回来的机器人回答的数据
public interface IChatPresenter {
void send(String userText);
void getAnswer(String answer);
}
我们还是写一个IPresenter类,我们在构造方法中接收IChatView对象,和一个发送数据list、一个发送人list,以及新建了一个UserModel对象
public class IPresenter implements IChatPresenter {
private UserModel userModel;
private IChatView iChatView;
int kang=0;
int user=1;
List<String>Text;
List<Integer>Text_type;
public IPresenter(IChatView iChatView,List<String>Text,List<Integer>Text_type)
{
this.iChatView=iChatView;
userModel=new UserModel(this);
this.Text=Text;
this.Text_type=Text_type;
}
@Override
public void send(String userText) {
Text.add(userText);
Text_type.add(user);
iChatView.clearEdit();
iChatView.updateUI(Text, Text_type);
userModel.getAnswer(userText);
}
@Override
public void getAnswer(String answer) {
if(answer!=null)
{
Text.add(answer);
Text_type.add(kang);
}
iChatView.updateUI(Text, Text_type);
}
}
这就是比较核心一部分了
send:就是负责将发送的话加入发送数据list中,并且将其标记为user,然后调用view层的两个方法,将输入框清空,并且将自己发送的话更新上去,并启动UserModel得到回答方法
getAnswer:这是一个回调函数,负责得到UserModel中网络请求后回调回来的机器人的回答,并且更新到UI上
3.我们接下来写model层,model层只有一个方法就是得到回答
public interface IChatModel {
void getAnswer(String text);
}
我们还是写一个UserModel类(这里就不贴出来占版面了,我后面会把github地址贴出来
我们在构造函数中只写了一个得到IPresenter的对象,因为我们要在网络请求后进行回调,这就是model对于数据的操作
public UserModel(IPresenter iPresenter)
{
this.iPresenter=iPresenter;
}
通过这个小demo,我们看到在presenter中我们用两个方法,如同两根绳子一样把view层和model层紧紧的拉到了一起,而这又不像以前的模式view和model有着超高的耦合度,MVP的优点大家可以看到就是可以明显的解耦,view中有presenter的对象,presenter有view和model的对象,model有presenter的对象,整体就是这样的。
4.项目地址https://github.com/zangjunhao/Android_MVP_Pattern,菜鸡希望能有个星