什么是低代码?低代码开发平台靠谱吗?低代码平台优缺点
511
2022-05-29
概况
做android开发,有时我们会采用MVP模式,把业务逻辑从Activity中分解出来。但是Presenter的生命周期不容易管理。对于一个复杂的Activity和Fragment来说,可能绑定了多个Presenter、Manager或者View,代码写起来就会很复杂。尤其是当这些被其他人复用的时候,很难让别人也注意到这一点,很容易发生内存溢出问题。
LifeCycle
Google推出的LifeCycle就可以解决辅助类的生命周期问题。
在API 26.1.0之后,android.support.v4.app中的FragmentActivity和Fragment都集成了LifeCycle的相关功能。
LiveData 和 ViewModel 生命周期组件是 Android 官方架构组件中的核心组件, 它可以使各种实例作为观察者与 Activity 和 Fragment 等具有生命周期特性的组件绑定在一起。我们将需要绑定生命周期的实例注册给该组件, 该组件就会在指定的某个生命周期方法执行时通知这个实例。它们用到了观察者模式。
LiveData
LiveData是一个可观察的数据持有者类。与常见的观察者不同,LiveData是有生命周期感知的。这种感知确保LiveData只更新处于生命周期状态内的应用程序组件(这一点太重要了)。
ViewModel
ViewModel 有两个功能, 第一个功能可以使 ViewModel 以及 ViewModel 中的数据在屏幕旋转或配置更改引起的 Activity 重建时存活下来, 重建后数据可继续使用; 第二个功能可以帮助开发者轻易实现 Fragment 与 Fragment 之间, Activity 与 Fragment 之间的通讯以及共享数据。
使用方法
通过创建MyViewModel extends ViewModel
在MyViewModel内部新建MutableLiveData
在Activity 或 Fragment中获取获取MyViewModel里的MutableLiveData并添加监听 viewModel.liveData.observer()
实例
我们以一个登录页LogActivity来举例说明吧。一般我们把业务交给ViewModel来处理。View则根据数据的变化来做调整,这部分是写在Fragment或Activity类里。
(1)分析登录页LoginActivity的需求
登录数据有效性验证,如用户名、密码的有效性验证,可以用一个类来记录这些登录表单的状态:
class LoginFormState { @Nullable private Integer usernameError;// 用户名错误 @Nullable private Integer passwordError;// 密码错误 // 我们用这个字段来控制登录按钮的状态 private boolean isDataValid; LoginFormState(@Nullable Integer usernameError, @Nullable Integer passwordError) { this.usernameError = usernameError; this.passwordError = passwordError; this.isDataValid = false; } LoginFormState(boolean isDataValid) { this.usernameError = null; this.passwordError = null; this.isDataValid = isDataValid; } @Nullable Integer getUsernameError() { return usernameError; } @Nullable Integer getPasswordError() { return passwordError; } boolean isDataValid() { return isDataValid; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
当数据有效性通过后,就开始登录,登录或成功或失败,我们用一个类来记录这些登录的结果:
class LoginResult { @Nullable private LoggedInUserView success; // 成功则返回数据 @Nullable private Integer error; // 错误则返回一个错误码 LoginResult(@Nullable Integer error) { this.error = error; } LoginResult(@Nullable LoggedInUserView success) { this.success = success; } @Nullable LoggedInUserView getSuccess() { return success; } @Nullable Integer getError() { return error; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
成功返回的数据的类:
class LoggedInUserView { private String displayName; //... other data fields that may be accessible to the UI LoggedInUserView(String displayName) { this.displayName = displayName; } String getDisplayName() { return displayName; } }
1
2
3
4
5
6
7
8
9
10
11
12
(2)以上这些需求,都将在LoginViewModel里帮我们完成这些数据校验和登录等数据逻辑。
由于在LoginActivity里要通过以下这种方式来获得LoginViewModel:
loginViewModel = ViewModelProviders.of(this, new LoginViewModelFactory()) .get(LoginViewModel.class);
1
2
因此我们要先建一个工厂类LoginViewModelFactory来创建我们的LoginViewModel:
public class LoginViewModelFactory implements ViewModelProvider.Factory { @NonNull @Override @SuppressWarnings("unchecked") public
1
2
3
4
5
6
7
8
9
10
11
12
13
从上面我们可以看到在创建LoginViewModel时传了一个LoginRepository单例进去。LoginRepository在实例化时传了一个LoginDataSource实例进去。
根据前面的分析我们可知LoginViewModel会提供登录及表单数据的有效性验证,但是如果需要共享登录的方法,甚至退出登录的方法、登录的状态、登录后用户的信息我们该怎么办呢?很简单只要将这些部分放在一个单例类里就好了。在我们这里就是LoginRepository这个类来充当共享的单例类。它的代码如下:
public class LoginRepository { private static volatile LoginRepository instance; private LoginDataSource dataSource; // If user credentials will be cached in local storage, it is recommended it be encrypted // @see https://developer.android.com/training/articles/keystore private LoggedInUser user = null; // private constructor : singleton access private LoginRepository(LoginDataSource dataSource) { this.dataSource = dataSource; } public static LoginRepository getInstance(LoginDataSource dataSource) { if (instance == null) { instance = new LoginRepository(dataSource); } return instance; } // 用户的登录状态,用户已登录则 返回true,否则返回false public boolean isLoggedIn() { return user != null; } // 退出时,清空LoginRepository单例类里所有的数据 public void logout() { user = null; dataSource.logout(); } // 登录成功后,我们就将用户的信息保存在LoginRepository单例类里 private void setLoggedInUser(LoggedInUser user) { this.user = user; // If user credentials will be cached in local storage, it is recommended it be encrypted // @see https://developer.android.com/training/articles/keystore } // 共享的登录方法 public Result
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
用户数据实体类:
public class LoggedInUser { private String userId; private String displayName; public LoggedInUser(String userId, String displayName) { this.userId = userId; this.displayName = displayName; } public String getUserId() { return userId; } public String getDisplayName() { return displayName; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
登录结果的实体类:
public class Result
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
负责处理用户登录和验证,并获取用户数据的数据源:
public class LoginDataSource { public Result
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
LoginViewModel登场:
public class LoginViewModel extends ViewModel { // 持有一个可观察的数据LoginFormState的LiveData类 private MutableLiveData
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
前面都是在讲LoginViewModel,最后我们讲一讲在LoginActivity里如何使用它:
package com.tisson.kmc.ui.login; import android.app.Activity; import android.arch.lifecycle.Observer; import android.arch.lifecycle.ViewModelProviders; import android.content.Intent; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.annotation.StringRes; import android.support.v7.app.AppCompatActivity; import android.text.Editable; import android.text.TextWatcher; import android.view.KeyEvent; import android.view.View; import android.view.inputmethod.EditorInfo; import android.widget.Button; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import com.tisson.kmc.MainActivity; import com.tisson.kmc.R; import com.tisson.kmc.ui.login.LoginViewModel; import com.tisson.kmc.ui.login.LoginViewModelFactory; public class LoginActivity extends AppCompatActivity { private LoginViewModel loginViewModel; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); // 获取ViewModel loginViewModel = ViewModelProviders.of(this, new LoginViewModelFactory()) .get(LoginViewModel.class); final EditText usernameEditText = findViewById(R.id.username); final EditText passwordEditText = findViewById(R.id.password); final Button loginButton = findViewById(R.id.login); final ProgressBar loadingProgressBar = findViewById(R.id.loading); // 观察表单数据的变化 loginViewModel.getLoginFormState().observe(this, new Observer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
Demo已在Github上了,欢迎下载学习。
Android
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。