Android笔记(28)MVVM架构过程
16lz
2021-12-04
1.加依赖包
apply plugin: 'com.android.application'android { compileSdkVersion 25 buildToolsVersion "26.0.1" defaultConfig { applicationId "com.example.myapplication" minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionName "1.0" aaptOptions.cruncherEnabled = false aaptOptions.useNewCruncher = false testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } //重点 dataBinding{ enabled = true } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }}dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) //UI dependency compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.android.support:design:25.3.1' compile 'com.android.support:recyclerview-v7:25.3.1' compile 'com.android.support:cardview-v7:25.3.1' // rx android compile 'com.jakewharton.rxbinding:rxbinding:0.4.0' compile 'io.reactivex:rxjava:1.0.16' compile 'io.reactivex:rxandroid:1.0.1' // gson compile 'com.google.code.gson:gson:2.7' // okhttp compile 'com.squareup.okhttp3:okhttp:3.9.0' compile 'com.squareup.okhttp3:logging-interceptor:3.9.0' compile 'com.github.simonpercic:oklog3:2.2.0' // retrofit compile 'com.squareup.retrofit2:retrofit:2.0.0' compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0' compile 'com.squareup.retrofit2:converter-gson:2.0.0' // let the Retorfit work with Rxjava compile 'com.jakewharton:butterknife:8.4.0' compile 'com.android.support.constraint:constraint-layout:1.0.2' testCompile 'junit:junit:4.12'}
2.新建APP类
import android.app.Application;public class App extends Application { @Override public void onCreate() { super.onCreate(); initEnv(); } //初始化app环境 private void initEnv(){ //初始化网络组件 APIFactory.init(); }}
3.AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapplication"> <application android:name=".App" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".LoginActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> intent-filter> activity> application>manifest>
4.在values中新建attrs.xml文件
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="ValidatedInputTextLayout"> <attr name="autoValidate" format="boolean" /> <attr name="autoTrim" format="boolean" /> <attr name="isRequired" format="boolean" /> <attr name="requiredValidationMessage" format="string" /> <attr name="minLength" format="integer"> <enum name="zero" value="0" /> attr> <attr name="maxLength" format="integer"> <enum name="indefinite" value="-1" /> attr> <attr name="lengthValidationMessage" format="string" /> <attr name="regex" format="string" /> <attr name="regexValidationMessage" format="string" /> declare-styleable>resources>
5.新建ValidatedTextInputLayout类
import android.content.Context;import android.content.res.TypedArray;import android.support.design.widget.TextInputLayout;import android.text.Editable;import android.text.TextWatcher;import android.util.AttributeSet;import java.util.ArrayList;import java.util.List;public class ValidatedTextInputLayout extends TextInputLayout { private List mValidators; private boolean mAutoValidate = false; private boolean mAutoTrimValue = false; public ValidatedTextInputLayout(Context context) { super(context); initialize(); } public ValidatedTextInputLayout(Context context, AttributeSet attrs) { super(context, attrs); initialize(); initializeCustomAttrs(context, attrs); } public ValidatedTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initialize(); initializeCustomAttrs(context, attrs); } private void initialize() { if (!isInEditMode()) { mValidators = new ArrayList<>(); this.post(new Runnable() { @Override public void run() { if (!getEditText().isInEditMode()) initializeTextWatcher(); } }); } } private void initializeCustomAttrs(Context context, AttributeSet attrs) { if (!isInEditMode()) { TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable .ValidatedInputTextLayout, 0, 0); try { mAutoTrimValue = typedArray.getBoolean(R.styleable.ValidatedInputTextLayout_autoTrim, false); mAutoValidate = typedArray.getBoolean(R.styleable .ValidatedInputTextLayout_autoValidate, false); initRequiredValidation(context, typedArray); initLengthValidation(context, typedArray); } finally { typedArray.recycle(); } } } private void initRequiredValidation(Context context, TypedArray typedArray) { if (typedArray.getBoolean(R.styleable.ValidatedInputTextLayout_isRequired, false)) { String errorMessage = typedArray.getString(R.styleable .ValidatedInputTextLayout_requiredValidationMessage); if (errorMessage == null) errorMessage = context.getString(R.string.default_required_validation_message); addValidator(new RequiredValidator(errorMessage)); } } private void initLengthValidation(Context context, TypedArray typedArray) { int minLength = typedArray.getInteger(R.styleable.ValidatedInputTextLayout_minLength, LengthValidator.LENGTH_ZERO); int maxLength = typedArray.getInteger(R.styleable.ValidatedInputTextLayout_maxLength, LengthValidator.LENGTH_INDEFINITE); if (!(minLength == LengthValidator.LENGTH_ZERO && maxLength == LengthValidator .LENGTH_INDEFINITE)) { String errorMessage = typedArray.getString(R.styleable .ValidatedInputTextLayout_lengthValidationMessage); if (errorMessage == null) { if (minLength == LengthValidator.LENGTH_ZERO) { errorMessage = context.getString(R.string.default_required_length_message_max, maxLength); } else if (maxLength == LengthValidator.LENGTH_INDEFINITE) { errorMessage = context.getString(R.string .default_required_length_message_min, minLength); } else { errorMessage = context.getString(R.string .default_required_length_message_min_max, minLength, maxLength); } } addValidator(new LengthValidator(minLength, maxLength, errorMessage)); } } private void initializeTextWatcher() { getEditText().addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (isAutoValidated()) validate(); else setError(null); } @Override public void afterTextChanged(Editable s) { } }); } public void clearValidators() { mValidators.clear(); setErrorEnabled(false); } public void addValidator(BaseValidator pValidator) { mValidators.add(pValidator); setErrorEnabled(true); } public void autoValidate(boolean flag) { mAutoValidate = flag; } public boolean isAutoValidated() { return mAutoValidate; } public void autoTrimValue(boolean flag) { mAutoTrimValue = flag; } public boolean isAutoTrimEnabled() { return mAutoTrimValue; } public boolean validate() { boolean status = true; String text = getValue(); for (IValidator validator : mValidators) { if (!validator.isValid(text)) { setError(validator.getErrorMessage()); status = false; break; } else { setError(null); } } return status; } public String getValue() { if (isAutoTrimEnabled()) return getEditText().getText().toString().trim(); else return getEditText().getText().toString(); }}
6.新建BaseValidator类
import android.support.annotation.NonNull;public abstract class BaseValidator implements IValidator { protected String mErrorMessage; public BaseValidator(@NonNull String pErrorMessage) { setErrorMessage(pErrorMessage); } @Override public abstract boolean isValid(String pText); @Override public void setErrorMessage(@NonNull String pErrorMessage) { mErrorMessage = pErrorMessage; } @Override public String getErrorMessage() { return mErrorMessage; }}
7.新建LengthValidator类
import android.support.annotation.NonNull;public class LengthValidator extends BaseValidator { public static final int LENGTH_INDEFINITE = -1; public static final int LENGTH_ZERO = 0; private int mMinimumLength = LENGTH_ZERO; private int mMaximumLength = LENGTH_INDEFINITE; public LengthValidator(@NonNull String pErrorMessage) { super(pErrorMessage); } public LengthValidator(int pMaximumLength, @NonNull String pErrorMessage) { super(pErrorMessage); mMaximumLength = pMaximumLength; } public LengthValidator(int pMinimumLength, int pMaximumLength, @NonNull String pErrorMessage) { super(pErrorMessage); mMinimumLength = pMinimumLength; mMaximumLength = pMaximumLength; } @Override public boolean isValid(String pText) { int length = pText.length(); if (getMaximumLength() == LENGTH_INDEFINITE) { return length >= getMinimumLength(); } else { return (length >= getMinimumLength() && length <= getMaximumLength()); } } public void setMinimumLength(int pMinimumLength) { mMinimumLength = pMinimumLength; } public void setMaximumLength(int pMaximumLength) { mMaximumLength = pMaximumLength; } public int getMinimumLength() { return mMinimumLength; } public int getMaximumLength() { return mMaximumLength; }}
8.新建RequiredValidator类
public class RequiredValidator extends BaseValidator { public RequiredValidator(String pErrorMessage) { super(pErrorMessage); } @Override public boolean isValid(String pText) { return !pText.isEmpty(); }}
9.新建IValidator接口
public interface IValidator { boolean isValid(String pText); void setErrorMessage(String pErrorMessage); String getErrorMessage();}
10.新建APIFactory类
import com.github.simonpercic.oklog3.OkLogInterceptor;import com.google.gson.Gson;import com.google.gson.GsonBuilder;import com.google.gson.JsonArray;import com.google.gson.JsonDeserializationContext;import com.google.gson.JsonDeserializer;import com.google.gson.JsonElement;import com.google.gson.JsonParseException;import com.lemner.hation.ykbb.BuildConfig;import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;import java.util.ArrayList;import java.util.Collections;import java.util.List;import okhttp3.OkHttpClient;import okhttp3.logging.HttpLoggingInterceptor;import retrofit2.Retrofit;import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;import retrofit2.converter.gson.GsonConverterFactory;public class APIFactory { private static APIService API_SERVICE; private static final String BASE_URL = "/*服务器网址*/"; private static final String PREFIX_BASE_URL = BASE_URL+""; public static final String PREFIX_BASE_IMG_URL = BASE_URL+""; private static Gson sGson; private static final int DEFAULT_TIMEOUT = 5; public static void init(){ OkLogInterceptor okLogInterceptor = OkLogInterceptor.builder().useAndroidLog(true).build(); HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient.Builder build=new OkHttpClient.Builder(); //if model is debug add a interceptor if (BuildConfig.DEBUG) { build .addInterceptor(okLogInterceptor); } OkHttpClient client = build.build(); API_SERVICE = new Retrofit.Builder() .baseUrl(PREFIX_BASE_URL) .client(client) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create(buildGson())) .build().create(APIService.class); } public static APIService getApiService() { return API_SERVICE; } private static Gson buildGson() { if(sGson==null){ sGson = new GsonBuilder().setPrettyPrinting().setLenient().registerTypeHierarchyAdapter(List.class, new JsonDeserializer>() { @Override public List<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { if (json.isJsonArray()) { JsonArray array = json.getAsJsonArray(); Type itemType = ((ParameterizedType) typeOfT).getActualTypeArguments()[0]; List list = new ArrayList<>(); for (int i = 0,size=array.size(); i < size; i++) { JsonElement element = array.get(i); Object item = context.deserialize(element, itemType); list.add(item); } return list; } else { //和接口类型不符,返回空List return Collections.EMPTY_LIST; } } }).create(); } return sGson; }}
11.新建LoginBean类
package com.example.myapplication;public class LoginBean{ private String userid; public String getUserid() { return userid; } public void setUserid(String userid) { this.userid = userid; }}
12.新建APIService类
package com.example.myapplication;import retrofit2.http.GET;import retrofit2.http.Query;import rx.Observable;public interface APIService { //登录 @GET("userLogin.do") Observable login( @Query("username") String username, @Query("userpass") String userpass );}
13.新建activity_login.xml文件
<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" xmlns:validation="http://schemas.android.com/apk/res-auto"> <data> <variable name="loginViewModel" type="com.example.myapplication.LoginViewModel" /> data> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".LoginActivity"> <com.example.myapplication.ValidatedTextInputLayout app:errorTextAppearance="@style/Theme.AppCompat" android:id="@+id/validate_et_username" android:layout_width="match_parent" android:layout_height="wrap_content" validation:autoTrim="true" validation:isRequired="true"> <EditText android:id="@+id/et_username" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入用户名"/> com.example.myapplication.ValidatedTextInputLayout> <com.example.myapplication.ValidatedTextInputLayout app:errorTextAppearance="@style/Theme.AppCompat" android:id="@+id/validate_et_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="30dp" android:layout_marginRight="30dp" validation:autoTrim="true" validation:isRequired="true"> <EditText android:id="@+id/et_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入密码"/> com.example.myapplication.ValidatedTextInputLayout> <Button android:id="@+id/bt_login" android:layout_width="100dp" android:layout_height="40dp" android:text="登录" android:onClick="@{loginViewModel::onClickEvent}"/> LinearLayout>layout>
14.新建LoginViewModel类
import android.content.Context;import android.view.View;import android.widget.Toast;import rx.Subscriber;import rx.android.schedulers.AndroidSchedulers;import rx.schedulers.Schedulers;public class LoginViewModel{ protected Context context; private LoginViewModelContract.LoginView loginView; public LoginViewModel(LoginViewModelContract.LoginView loginView ,Context context) { this.context=context; this.loginView = loginView; } public void onClickEvent(View view) { switch (view.getId()) { case R.id.bt_idcode: loginView.postLogin(); break; } } public void destroy() { } public void postLogin(String username , String pasword){ APIFactory.getApiService().login(username,pasword) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { Toast.makeText(context, "网络连接不畅",Toast.LENGTH_SHORT).show(); } @Override public void onNext(LoginBean loginBean) { if (true/*没写*/){ //context.startActivity(new Intent(context,MainActivity.class));//成功后跳转 }else { Toast.makeText(context , "账号或密码错误!",Toast.LENGTH_SHORT).show(); } } }); }}
15.新建LoginViewModelContract接口
public interface LoginViewModelContract { interface LoginView{ void showLoadingDialog(); void dismissLoadingDialog(); void postLogin(); }}
16.新建LoginActivity类
import android.app.ProgressDialog;import android.databinding.DataBindingUtil;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import android.view.View;import com.example.myapplication.databinding.ActivityLoginBinding;import butterknife.ButterKnife;public class LoginActivity extends AppCompatActivity implements LoginViewModelContract.LoginView{ private LoginViewModel loginViewModel; private ActivityLoginBinding activityLoginBinding; private ProgressDialog mProgressDialog; protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setView(); initView(); ButterKnife.bind(this); } public void initView() { } public View setView() { activityLoginBinding = DataBindingUtil.setContentView(this , R.layout.activity_login); loginViewModel = new LoginViewModel(this,LoginActivity.this); activityLoginBinding.setLoginViewModel(loginViewModel); return activityLoginBinding.getRoot(); } public void onViewDestroy() { loginViewModel.destroy(); } public void showLoadingDialog() { mProgressDialog.show(); } public void dismissLoadingDialog() { mProgressDialog.dismiss(); } public void postLogin() { loginViewModel.postLogin(activityLoginBinding.etUsername.getText().toString() , activityLoginBinding.etPassword.getText().toString()); }}
更多相关文章
- Android之获取Android唯一ID
- Android(安卓)5.0 Input初始化
- 博客技术资料整理
- android TabHost小结
- android TabHost小结
- Android之Audio初探
- Android的Camera系统结构
- 系出名门Android(9) - 数据库支持(SQLite),
- Android图形系统的底层实现