安卓常用架构 MVC & MVP & MVVM
一、MVC
1. 简介
M
是指业务模型,V
是指用户界面,C
是控制器
全名 Model View Controller
业务模型Model
- 用户视图View
- 控制器Controller
2. 解释
View
层其实就是程序的UI
界面,用于向用户展示数据以及接收用户的输入Model
层就是JavaBean
实体类,用于保存实例数据Controller
控制器用于更新UI
界面和数据实例
4. 项目结构
建立3个包 beans、views、controllers分别存放对应的模型、视图、控制层
3. 优缺点
- 缺点:
Activity
既是C
又是V
,既有显示UI
界面,又有登陆操作。所有的代码都是在MainActivity
// Model
public class User {
private String name;
private String email;
// Getters and Setters
}
// View
public class UserView {
public void displayUser(String name, String email) {
System.out.println("Name: " + name);
System.out.println("Email: " + email);
}
}
// Controller
public class UserController {
private User model;
private UserView view;
public UserController(User model, UserView view) {
this.model = model;
this.view = view;
}
public void updateUser(String name, String email) {
model.setName(name);
model.setEmail(email);
}
public void displayUser() {
String name = model.getName();
String email = model.getEmail();
view.displayUser(name, email);
}
}
// Usage
public static void main(String[] args) {
User user = new User();
user.setName("John");
user.setEmail("john@example.com");
UserView userView = new UserView();
UserController userController = new UserController(user, userView);
// Update user information
userController.updateUser("Jane", "jane@example.com");
// Display user information
userController.displayUser();
}
java
二、MVP
1. 简介
M
是指业务模型,V
是指用户界面,P
是逻辑层(Model
和View
之间的桥梁)
全名 Model View Presenter
业务模型Model
- 用户视图View
- 逻辑层Presenter
2. 解释
把Activity
中的UI
逻辑抽象成View
接口,把业务逻辑抽象成Presenter
接口,Model
类还是原来的Model
类
- 分离视图逻辑和业务逻辑,降低耦合
Activity
只处理生命周期的任务,代码简洁- 视图逻辑和业务逻辑抽象到了
View
和Presenter
中,提高阅读性 Presenter
被抽象成接口,可以有多种具体的实现- 业务逻辑在
Presenter
中,避免后台线程引用Activity
导致内存泄漏
3.项目结构
建立3个包 beans、views、presenters分别存放对应的模型、视图、控制层
4. 优缺点
Presenter
更新UI
需要在主线程Presenter
更新UI
无法确保UI
是否已经被销毁
5. 项目示例
IArticlePresenterCallback.java
package cool.hyz.xujiayi.callbacks;
import cool.hyz.xujiayi.beans.Article;
/**
* Created by Lib on 2022/4/20
* Best Wishes !
*/
public interface IArticlePresenterCallback {
/**
* 数据加载完成
* @param article Article
*/
void onArticleInfoLoaded(Article article);
/**
* 网络不佳
*/
void onNetworkError();
/**
* 数据为空
*/
void onEmpty();
}
java
IArticlePresenter.java
package cool.hyz.xujiayi.services.interfaces;
import java.io.IOException;
import cool.hyz.xujiayi.callbacks.IArticlePresenterCallback;
/**
* Created by Lib on 2022/4/20
* Best Wishes !
*/
public interface IArticlePresenter {
/**
* 获取Article信息
* @param id id
* @throws IOException IOException
*/
void getArticleInfo(String id) throws IOException;
/**
* 注册Presenter
* @param callback IArticlePresenterCallback
*/
void registerCallback(IArticlePresenterCallback callback);
/**
* 取消注册Presenter
* @param callback IArticlePresenterCallback
*/
void unRegisterCallback(IArticlePresenterCallback callback);
}
java
ArticlePresenter.java
package cool.hyz.xujiayi.services;
import com.google.gson.Gson;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import cool.hyz.xujiayi.beans.Article;
import cool.hyz.xujiayi.callbacks.IArticlePresenterCallback;
import cool.hyz.xujiayi.services.interfaces.IArticlePresenter;
import cool.hyz.xujiayi.utils.Constance;
import cool.hyz.xujiayi.utils.HttpRequest;
/**
* Created by Lib on 2022/4/20
* Best Wishes !
*/
public class ArticlePresenter implements IArticlePresenter {
private IArticlePresenterCallback mCallback;
private static final List<IArticlePresenterCallback> sCallback = new ArrayList<>();
HttpRequest request = new HttpRequest();
@Override
public void getArticleInfo(String id) {
new Thread(() -> {
Article article = null;
try {
article = new Gson().fromJson(request.GET(Constance.API.ARTICLE_DETAIL+id), Article.class);
} catch (IOException e) {
e.printStackTrace();
}
mCallback.onArticleInfoLoaded(article);
}).start();
}
@Override
public void registerCallback(IArticlePresenterCallback callback) {
if (callback != null && !sCallback.contains(callback)) {
mCallback = callback;
sCallback.add(mCallback);
}
}
@Override
public void unRegisterCallback(IArticlePresenterCallback callback) {
if (callback != null && sCallback.contains(callback)) {
sCallback.remove(callback);
}
}
}
java
ArticleActivity.java
package cool.hyz.xujiayi;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.squareup.picasso.Picasso;
import cool.hyz.xujiayi.bases.BaseApplication;
import cool.hyz.xujiayi.beans.Article;
import cool.hyz.xujiayi.beans.ArticleDetailBean;
import cool.hyz.xujiayi.beans.CommentListBean;
import cool.hyz.xujiayi.callbacks.IArticlePresenterCallback;
import cool.hyz.xujiayi.services.ArticlePresenter;
/**
* Created by Lib on 2022/4/21
* Best Wishes !
*/
public class ArticleActivity extends Activity implements IArticlePresenterCallback {
public static final String TAG = "ArticleActivity";
private ArticlePresenter mPresenter;
private ImageView mCover;
private TextView mTitle;
private TextView mCreateTime;
private TextView mUpdateTime;
private TextView mCategory;
private String mId;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.page_article);
initView();
initPresenter();
initData();
}
private void initView() {
mTitle = findViewById(R.id.article_title);
mCover = findViewById(R.id.article_cover);
mCreateTime = findViewById(R.id.article_create_time);
mUpdateTime = findViewById(R.id.article_update_time);
mCategory = findViewById(R.id.article_category);
}
private void initPresenter() {
mPresenter = new ArticlePresenter();
//注册Presenter
mPresenter.registerCallback(this);
}
private void initData() {
Intent intent = getIntent();
mId = intent.getStringExtra("id");
//Presenter请求数据
mPresenter.getArticleInfo(mId);
}
@Override
public void onArticleInfoLoaded(Article article) {
//更新UI
BaseApplication.getHandler().post(() -> {
Picasso.with(this).load(article.getArticleCover().startsWith("//") ? "https:" + article.getArticleCover() : article.getArticleCover()).into(mCover);
mCreateTime.setText(article.getCreateTime().substring(0, 10));
mUpdateTime.setText(article.getUpdateTime() != null ? article.getUpdateTime().substring(0, 10) : article.getCreateTime().substring(0, 10));
mCategory.setText(article.getCategoryName());
String articleTitle = article.getArticleTitle();
mTitle.setText(articleTitle);
});
}
@Override
public void onNetworkError() {
//更新UI
}
@Override
public void onEmpty() {
//更新UI
}
}
java
三、MVVM
1. 简介
M
是指业务模型,V
是指用户界面,VM
是逻辑层
全名 Model View ViewModel
业务模型Model
- 用户视图View
- 应用程序逻辑控制器ViewModel
2. 解释
把Activity
中的UI
逻辑抽象成View
接口,把业务逻辑抽象成Presenter
接口,Model
类还是原来的Model
类
- 分离视图逻辑和业务逻辑,降低耦合
Activity
只处理生命周期的任务,代码简洁- 视图逻辑和业务逻辑抽象到了
View
和Presenter
中,提高阅读性 Presenter
被抽象成接口,可以有多种具体的实现- 业务逻辑在
Presenter
中,避免后台线程引用Activity
导致内存泄漏
3.项目结构
建立4个包 beans、views、models、repositories分别存放对应的模型、视图、控制层、存储层
4. 优缺点
Presenter
更新UI
需要在主线程Presenter
更新UI
无法确保UI
是否已经被销毁
5. 示例
// Model
public class User {
private String name;
private String email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
// View
public class MainActivity extends AppCompatActivity {
private EditText nameEditText;
private EditText emailEditText;
private Button saveButton;
private UserViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialize views
nameEditText = findViewById(R.id.nameEditText);
emailEditText = findViewById(R.id.emailEditText);
saveButton = findViewById(R.id.saveButton);
// Initialize view model
viewModel = new ViewModelProvider(this).get(UserViewModel.class);
// Set observer on user live data
viewModel.getUserLiveData().observe(this, new Observer<User>() {
@Override
public void onChanged(User user) {
nameEditText.setText(user.getName());
emailEditText.setText(user.getEmail());
}
});
// Set click listener on save button
saveButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String name = nameEditText.getText().toString();
String email = emailEditText.getText().toString();
viewModel.updateUser(name, email);
}
});
}
}
// ViewModel
public class UserViewModel extends ViewModel {
private MutableLiveData<User> userLiveData = new MutableLiveData<>();
private User user = new User();
public UserViewModel() {
userLiveData.setValue(user);
}
public LiveData<User> getUserLiveData() {
return userLiveData;
}
public void updateUser(String name, String email) {
user.setName(name);
user.setEmail(email);
userLiveData.setValue(user);
}
}
java