參考:
http://www.reibang.com/p/996d76b2317f
http://www.reibang.com/p/fed20fc304b7
文章名稱都懶得改恩商,照搬過來了。
效果圖
image.png
代碼結(jié)構(gòu)
image.png
整體架構(gòu)MVVM,網(wǎng)絡(luò)請求用的retrofit2 + rxjava2研叫,數(shù)據(jù)綁定使用的 databinding嚷炉。
1.View層就是展示數(shù)據(jù)的申屹,以及接收到用戶的操作傳遞給viewModel層哗讥,通過dataBinding實現(xiàn)數(shù)據(jù)與view的單向綁定或雙向綁定
2.Model層最重要的作用就是獲取數(shù)據(jù)了胞枕,當(dāng)然不止于此决乎,model層將結(jié)果通過接口的形式傳遞給viewModel層
3.ViewModel 層通過調(diào)用model層獲取數(shù)據(jù)派桩,以及業(yè)務(wù)邏輯的處理铆惑。
1.LoginActivity 的布局
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
</data>
<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/rover_color_background"
android:orientation="vertical">
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:layout_gravity="center_horizontal"
android:background="@mipmap/login_title" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:background="@drawable/background_white_shape"
android:layout_marginTop="30dp"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/relay1"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="20dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="@drawable/background_grey_shape_stroke">
<ImageView
android:id="@+id/img1"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_centerVertical="true"
android:layout_marginEnd="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginStart="10dp"
android:src="@mipmap/login_user" />
<View
android:layout_width="0.5dp"
android:layout_height="match_parent"
android:layout_toEndOf="@+id/img1"
android:layout_toRightOf="@+id/img1"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:background="@color/ranger_color_blue"
android:id="@+id/view1" />
<EditText
android:id="@+id/name_edit"
style="@style/Ranger_MSize_GColor"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_centerVertical="true"
android:layout_gravity="center_vertical"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:layout_toEndOf="@+id/view1"
android:layout_toRightOf="@+id/view1"
android:background="@drawable/rover_white_shape"
android:gravity="center_vertical"
android:hint="請輸入手機號"
android:maxLength="11" />
<ImageView
android:id="@+id/delete1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginEnd="18dp"
android:layout_marginRight="18dp"
android:background="@mipmap/input_close"
android:padding="10dp"
android:visibility="gone" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/relay2"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="20dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="20dp"
android:background="@drawable/background_grey_shape_stroke">
<ImageView
android:id="@+id/img2"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_centerVertical="true"
android:layout_marginEnd="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginStart="10dp"
android:src="@mipmap/login_pwd" />
<View
android:layout_width="0.5dp"
android:layout_height="match_parent"
android:layout_toEndOf="@+id/img2"
android:layout_toRightOf="@+id/img2"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:background="@color/ranger_color_blue"
android:id="@+id/view2" />
<EditText
android:id="@+id/pass_edit"
style="@style/Ranger_MSize_GColor"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_centerVertical="true"
android:layout_gravity="center_vertical"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:layout_toEndOf="@+id/view2"
android:layout_toRightOf="@+id/view2"
android:background="@drawable/rover_white_shape"
android:gravity="center_vertical"
android:hint="請輸入密碼"
android:inputType="textPassword" />
<ImageView
android:id="@+id/delete2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginEnd="18dp"
android:layout_marginRight="18dp"
android:background="@mipmap/input_close"
android:padding="10dp"
android:visibility="gone" />
</RelativeLayout>
</LinearLayout>
<Button
android:id="@+id/login_button"
style="@style/Ranger_BSize_WColor"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="35dp"
android:background="@drawable/background_blue_shape"
android:text="登錄" />
</LinearLayout>
</layout>
2.LoginActivity
public class LoginActivity extends AppCompatActivity {
LoginActivityBinding binding;
LoginViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this,R.layout.login_activity);
viewModel = new LoginViewModel();
binding.loginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
login();
}
});
}
private void login() {
if (TextUtils.isEmpty(binding.nameEdit.getEditableText().toString())) {
Toast.makeText(getApplication(), "請輸入賬號脑慧!", Toast.LENGTH_SHORT).show();
return;
}
if (TextUtils.isEmpty(binding.passEdit.getEditableText().toString())) {
Toast.makeText(getApplication(), "請輸入密碼闷袒!", Toast.LENGTH_SHORT).show();
return;
}
viewModel.login(binding.nameEdit.getEditableText().toString(),binding.passEdit.getEditableText().toString());
}
3.LoginViewModel
public class LoginViewModel extends ViewModel {
private static final String TAG = "LoginViewModel";
private LoginModel model;
public LoginViewModel() {
model = new LoginModel();
}
public void login(String name, String pass) {
model.appLogin(name, pass, new INetWorkCallback<LoginResult>() {
@Override
public void onCallApiSuccess(LoginResult loginResult) {
android.util.Log.e(TAG,"---onCallApiSuccess---");
}
@Override
public void onCallApiFailure(Throwable throwable) {
android.util.Log.e(TAG,"---onCallApiFailure---");
}
@Override
public void onCompleted() {
android.util.Log.e(TAG,"---onCompleted---");
}
});
}
}
4.RetrofitService api地址
public interface RetrofitService {
/**
* 地址是測試地址囊骤,外網(wǎng)ping不通
*/
String HOST = "http://10.6.152.9:8091/";
/**
* 登錄</p>
* 作者:Bob</p>
* 日期:2020-03-07</p>
*
* @param body {"loginName":"111","loginPass":"123456"}
* @return 是否登錄成功
*/
@Headers({"Content-Type: application/json", "Accept: application/json"})
@POST("user/login")
Observable<LoginResult> appLogin(@Body RequestBody body);
}
5.LoginModel
public class LoginModel {
public void appLogin(final String loginName, final String pass, final INetWorkCallback<LoginResult> callback) {
final RequestBodyEntity.Login loginRequest = new RequestBodyEntity.Login();
loginRequest.loginName = loginName;
loginRequest.loginPass = pass;
final Gson gson = new Gson();
String gsonStr = gson.toJson(loginRequest);
RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), gsonStr);
RetrofitUtil.getInstance().getRetrofitService()
.appLogin(body)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new DisposableObserver<LoginResult>() {
@Override
public void onNext(LoginResult loginResult) {
callback.onCallApiSuccess(loginResult);
}
@Override
public void onError(Throwable e) {
callback.onCallApiFailure(e);
}
@Override
public void onComplete() {
callback.onCompleted();
}
});
}
}