序文
mvvm が登場してから長い時間が経ちましたが、ブロガーはあまり注目していませんでしたが、最近話題になったフレームワークや新しいフレームワークの多くは mvvm モデルに基づいて開発されているため、注目するのに時間がかかりました。
mvvm を学ぶ前に、まずデータビングを理解する必要があるかもしれません。バイドゥに行ってください。データビングを紹介するブログはたくさんあります。知識が十分に進んでいないため、ソースコードの解釈については説明しません。プロジェクトにデータビングを追加すると、findViewById もバターナイフ プラグインも必要なくなり、データビング機能はそれだけでなく、イベントやデータ変換をバインドすることもできます。まずはインターネットについて理解してから、
シンプルなパッケージングの旅を始めましょう
- BaseActivityパッケージ
- BaseFragmentのカプセル化
- BaseView統合インターフェイス メソッドのカプセル化
- BaseViewModelのカプセル化
- BaseExceptionエラー例外定義クラス
- BaseModelEntityインターフェースはデータ統合処理クラスを返します
- ネットワークリクエストフレームワークをカプセル化します。ここでは例としてRxjava2+Retrofitを取り上げます。
- 統合されたツール クラスのカプセル化と API 関連の構成のカプセル化この記事では、 BaseActivity、BaseFragment、BaseView、および BaseViewModelから
始めます。導入する必要があるライブラリは次のとおりです。
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
//放着没有及时回收造成RxJava内存泄漏
implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.2'
//Room的依赖引用
implementation 'androidx.room:room-runtime:2.2.5'
annotationProcessor 'androidx.room:room-compiler:2.2.5'
ベースアクティビティ
BaseActivity のカプセル化に関して最初に考えるのは、findViewById と setContentView を繰り返す必要がないため、抽象メソッドを定義できるということです。
/**
* 初始化布局
* @return 布局id
*/
protected abstract int getLayoutId();
もちろん、統合ツールバーをカプセル化することもでき、残りのページではツールバーを導入する必要があります。もちろん、ツールバーを導入する前に元のナビゲーション バーを削除する必要があります。
<style name="AppBaseTheme" parent="@style/Theme.AppCompat.Light.NoActionBar">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
<!--<item name="android:statusBarColor">@color/theme_backgroung_color</item>-->
<!--<item name="android:windowBackground">@color/window_background</item>-->
<item name="android:colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/themeColor</item>
</style>
<style name="AppTheme" parent="AppBaseTheme"/>
次に、アプリケーション ノードの下にテーマ テーマを導入します。
このとき、データビングの双方向バインディング機能を参照してみます。新しいツールバー スタイルのクラス ファイルを作成します。
/**
* Create by CherishTang on 2020/3/25 0025
* describe:toolbar配置
*/
public class ToolbarConfig extends BaseObservable {
private String title;
private @DrawableRes int backIconRes = R.mipmap.icon_fh_black;//toolbar返回按钮资源样式
private boolean defaultTheme = true;//toolbar的menu主题,默认主题为黑色
private int textColor = R.color.black;//标题字体颜色
private int bgColor = R.color.white;//标题背景色
private boolean isShowBackButton = true;//是否显示返回按钮
public ToolbarConfig() {
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getBackIconRes() {
return backIconRes;
}
public void setBackIconRes(int backIconRes) {
this.backIconRes = backIconRes;
}
public boolean isDefaultTheme() {
return defaultTheme;
}
public void setDefaultTheme(boolean defaultTheme) {
this.defaultTheme = defaultTheme;
}
public int getTextColor() {
return textColor;
}
public void setTextColor(int textColor) {
this.textColor = textColor;
}
public int getBgColor() {
return bgColor;
}
public void setBgColor(int bgColor) {
this.bgColor = bgColor;
}
public boolean isShowBackButton() {
return isShowBackButton;
}
public void setShowBackButton(boolean showBackButton) {
isShowBackButton = showBackButton;
}
}
次に、base_activity.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">
<data>
<variable
name="toolbarConfig"
type="com.jcloudsoft.demo.bean.base.ToolbarConfig" />
<import type="android.view.View" />
<import type="androidx.core.content.ContextCompat" />
<import type="androidx.annotation.LayoutRes" />
<import type="androidx.annotation.ColorRes" />
<variable
name="context"
type="android.content.Context" />
</data>
<LinearLayout
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/main_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/y96"
android:background="@{ContextCompat.getColor(context,toolbarConfig.bgColor)}"
android:minHeight="?attr/actionBarSize"
app:navigationIcon="@{ContextCompat.getDrawable(context,toolbarConfig.backIconRes)}"
android:theme="@style/ToolBarStyle_black">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:ellipsize="end"
android:maxLength="12"
android:maxLines="1"
android:text="@{toolbarConfig.title}"
android:textColor="@{ContextCompat.getColor(context,toolbarConfig.textColor)}"
android:textSize="@dimen/font_18"/>
</androidx.appcompat.widget.Toolbar>
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</layout>
上記のレイアウト ファイルに関していくつかの質問があるかもしれません。
1. コンテキスト オブジェクト。XML レイアウトでコンテキスト オブジェクトを返すことはできませんが、データビング双方向バインディングを使用してこのオブジェクトを XML レイアウトに渡すことはできます。または、直接行うこともできます。同じ戻りデータを返すようにメソッドをカスタマイズしても、効果は同じです
bind.setVariable(BR.context, this);
2. スタイル @style/ToolBarStyle_black の問題。理解できない場合は、ツールバーのスタイルをよりクールにしたい場合は、あまり説明せずに、カスタム ツールバーのブログ投稿を読んでコードを直接貼り付けることができます。もちろん、このアイデアを使用して、さらに関連する構成を追加することもできます
<style name="ToolBarStyle_black" parent="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<item name="actionMenuTextColor">@android:color/black</item> <!-- menu 敲定颜色-->
<item name="android:textSize">@dimen/font_14</item> <!-- 搞掂字体大小-->
<item name="android:textStyle">normal</item>
<item name="colorControlNormal">@color/black</item><!--图标颜色-->
<item name="overlapAnchor">false</item>
</style>
アクティビティにレイアウトを導入しますが、問題が発生します。一部のページにツールバーが必要ない場合はどうなるでしょうか? setVisibility ができません。低すぎます。まず、子アクティビティの抽象メソッドを定義して、ツールバーの表示と非表示を制御します。
/**
* 是否引用toolbar
* @return 默认显示
*/
protected boolean hasToolBar() {
return true;
}
別のタイトルテキストメソッドを定義する
/**
* 设置toolbar的title
* @return 标题
*/
public abstract String setTitleBar();
では、これらのメソッドをどのように参照すればよいのでしょうか? もちろん、データビングの双方向バインディング機能を使用すると、
//toolbarConfig是xml定义的name,setToolbarStyle()是我们刚才新建的toolbar配置类
bind.setVariable(BR.toolbarConfig, setToolbarStyle())
もちろん、ツールバーのスタイルを変更するには、サブアクティビティのインターフェイスを公開する必要があります。
/**
* 设置toolbar默认样式
*
* @return toolbar配置
*/
public ToolbarConfig setToolbarStyle() {
return new ToolBarSet().build();
}
ツールバーのスタイルをカスタマイズし、ニーズに応じて独自のメソッドを追加できます
/**
* 自定义toolbar样式类
*/
public class ToolBarSet {
private ToolbarConfig toolbarConfig;
public ToolBarSet() {
if (toolbarConfig == null) {
this.toolbarConfig = new ToolbarConfig();
}
toolbarConfig.setTitle(setTitleBar());
}
public ToolbarConfig getConfig(){
return toolbarConfig;
}
public ToolbarConfig build() {
return toolbarConfig;
}
public ToolBarSet setTitleTextColor(@ColorRes int colorRes) {
toolbarConfig.setTextColor(colorRes);
return this;
}
public ToolBarSet setBackIconRes(@DrawableRes int imgRes) {
toolbarConfig.setBackIconRes(imgRes);
return this;
}
public ToolBarSet setTitle(String title) {
toolbarConfig.setTitle(title);
return this;
}
public ToolBarSet setBgColor(@ColorRes int colorRes) {
toolbarConfig.setBgColor(colorRes);
return this;
}
public ToolBarSet setDefaultTheme(boolean defaultTheme) {
toolbarConfig.setDefaultTheme(defaultTheme);
return this;
}
public ToolBarSet setShowBackButton(boolean isShow) {
toolbarConfig.setShowBackButton(isShow);
return this;
}
}
そうするとツールバーのカスタムスタイルがバインドされてしまうので、ツールバーを導入するかどうかの問題はまだ解決されていないのでしょうか?データビングのバインディング レイアウト ファイルは次のように記述されます。
ViewDataBinding VDB = DataBindingUtil.setContentView(this, R.layout.base_activity)
これを見てください。インスピレーションはありますか? 次のことを行う必要があります:
1. UI ページにバインドするレイアウトは、base_activity にすることはできません。getLayoutId() によって返されるレイアウト ID である必要があります。 2. hasToolBar
( ) メソッドからツールバーの非表示を判断する データビング
でのレイアウトのバインドは、元のものとは若干異なりますが、すべてシステムのsetContentViewメソッドを使用するため、システムのsetContentViewメソッドを書き換えて、異なるバインド関係を実現できます。
@Override
public void setContentView(int layoutResID) {
if (hasToolBar()) {
//如果是引用toolbar布局的话我们根布局重写一下,需要引入base_activity作为根布局文件,然后把各ui页面的getLayoutId()定义的布局资源添加到根布局文件中去
super.setContentView(R.layout.base_activity);
FrameLayout container = findViewById(R.id.container);
mToolbar = findViewById(R.id.main_bar);
binding = DataBindingUtil.inflate(LayoutInflater.from(this), getLayoutId(), container, true);
mToolbar.setNavigationOnClickListener(v -> finish());
} else {
//如果不需要toolbar的话,我们直接就以getLayoutId()的布局资源id作为根布局
super.setContentView(layoutResID);
}
}
これを実行した後、onCreate で実装できます。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (hasToolBar()) {
toolbarBind = DataBindingUtil.setContentView(this, R.layout.base_activity);//我们需要定义一个属于toolbar的bind来控制toolbar的样式
toolbarBind.setVariable(BR.context, this);//给view传递context对象
toolbarBind.setVariable(BR.toolbarConfig, setToolbarStyle());
} else {
binding = DataBindingUtil.setContentView(this, getLayoutId());
}
}
ここでツールバー スタイルがパッケージ化されています。もちろん、Activity パッケージはまだ完成していません。いくつかのパブリック メソッドを追加できます。
/**
* 初始化布局
*/
public abstract void initView();
/**
* 设置数据
*/
public abstract void initData(Bundle bundle);
しかし、長い間話した後、まだ ViewModel を導入していません。心配しないでください。まずはフラグメントパッケージを紹介し、アクティビティのソースコードを以下の記事に掲載します
ベースフラグメント
アクティビティのカプセル化が先例になっているため、フラグメントのカプセル化ははるかに単純です。まず、必要なパブリック メソッドもいくつか定義します。
/**
* 该抽象方法就是 onCreateView中需要的layoutID
*
* @return
*/
protected abstract int getLayoutId();
/**
* 该抽象方法就是 初始化view
*
* @param view
* @param savedInstanceState
*/
protected abstract void initView(View view, Bundle savedInstanceState);
/**
* 执行数据的加载
*/
protected abstract void initData(Bundle bundle);
フラグメント内のリソース ファイルのバインドはアクティビティとは少し異なります
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container
, Bundle savedInstanceState) {
binding = DataBindingUtil.inflate(inflater, getLayoutId(), container, false);
return binding.getRoot();
}
フラグメントにバインドされたビュー レイアウトは後で役立つ可能性があるため、それを受け入れるビューを定義します。
protected View mContentView;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container
, Bundle savedInstanceState) {
binding = DataBindingUtil.inflate(inflater, getLayoutId(), container, false);
mContentView = binding.getRoot();
return mContentView;
}
次に、カスタマイズしたばかりの抽象メソッドを実装します。
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initData(getArguments() == null ? new Bundle() : getArguments());
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container
, Bundle savedInstanceState) {
binding = DataBindingUtil.inflate(inflater, getLayoutId(), container, false);
mContentView = binding.getRoot();
initView(mContentView, savedInstanceState);
return mContentView;
}
そうすれば、フラグメントの単純なカプセル化がはるかに簡単になります。
BaseView
Activity と Fragment をカプセル化した後、Toast、loading box などの多くのパブリック メソッドが欠落していることがわかりました。これらのメソッドは Fragment と Activity で共有されているため、インターフェイスを定義して、Activity と Fragment にそのメソッドを実装させることができます。本体ができる
public interface BaseView {
/**
* 显示dialog
*/
void showLoading(String dialogMessage);
/**
* 更新dialog
*/
void refreshLoading(String dialogMessage);
/**
* 隐藏 dialog
*/
void hideLoading();
/**
* 显示错误信息
*
* @param msg
*/
void showToast(String msg);
/**
* 错误码
*/
void onErrorCode(BaseModelEntity model);
}
その後、メソッド本体を BaseActivity と BaseFragment に実装するだけで済みます。
BaseViewModel
ここまで述べたところで、いよいよ ViewModel について話しましょう。
この話をする前に、LifeCycleを導入すべきだという人もいるかもしれない。私は答えられます:その必要はありません!!!!!LifeCycle インターフェースは androidx にデフォルトで実装されています。
特別な要件がない場合は、上記のとおりです。
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
Google がすでにインポートしているため、このライブラリはインポートできません
public class BaseViewModel extends AndroidViewModel {
public BaseViewModel(@NonNull Application application) {
super(application);
}
}
もちろん、今インターフェースbaseViewを導入する必要があります
public class BaseViewModel<V extends BaseView> extends AndroidViewModel {
protected V baseView;
public BaseViewModel(@NonNull Application application) {
super(application);
}
protected void setBaseView(V baseView) {
this.baseView = baseView;
}
public V getBaseView() {
return baseView;
}
}
現時点では、ViewModel に何が必要かまだわかりません。やみくもに書かないでください。使ってみるとわかります。ViewModel にたくさん書いたほうがよいでしょう。今しなければならないのは、次のことです。 BaseActivity の BaseViewModel もちろん、さまざまなアクティビティがありますが、さまざまな ViewModel があるため、すべての ViewModel を BaseViewModel から継承させ、BaseActivity にジェネリックとして導入することもできます。
public abstract class BaseActivity<VM extends BaseViewModel, VDB extends ViewDataBinding> extends AppCompatActivity implements BaseView {
public Context context;
Toolbar mToolbar;
public VM mViewModel;
protected VDB binding;
private BaseActivityBinding toolbarBind;
private CustomProgressDialog customProgressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = this;
if (hasToolBar()) {
toolbarBind = DataBindingUtil.setContentView(this, R.layout.base_activity);
toolbarBind.setVariable(BR.context, this);//给view传递context对象
toolbarBind.setVariable(BR.toolbarConfig, setToolbarStyle());
} else {
binding = DataBindingUtil.setContentView(this, getLayoutId());
}
createViewModel();
initView();
initData((getIntent() == null || getIntent().getExtras() == null) ? new Bundle() : getIntent().getExtras());
}
private void closeLoadingDialog() {
if (customProgressDialog != null && customProgressDialog.isShowing()) {
customProgressDialog.dismiss();
}
}
private void showLoadingDialog(String dialogMessage) {
if (customProgressDialog == null || !customProgressDialog.isShowing()) {
customProgressDialog = new CustomProgressDialog(context);
customProgressDialog.isShowBg(StringUtil.isEmpty(dialogMessage));
customProgressDialog.setMessage(dialogMessage);
customProgressDialog.show();
}
}
@Override
public void showLoading(String dialogMessage) {
runOnUiThread(() -> showLoadingDialog(dialogMessage));
}
@Override
public void refreshLoading(String dialogMessage) {
runOnUiThread(() -> {
if (customProgressDialog != null && customProgressDialog.isShowing()) {
customProgressDialog.setMessage(dialogMessage);
}
});
}
@Override
public void hideLoading() {
runOnUiThread(this::closeLoadingDialog);
}
@Override
public void showToast(String msg) {
runOnUiThread(() -> {
if (StringUtil.isEmpty(msg)) return;
ToastUtils.showShort(this, msg);
});
}
@Override
public void onErrorCode(BaseModelEntity model) {
if (model != null && (UserAccountHelper.isLoginPast(model.getCode()) || UserAccountHelper.isNoPermission(model.getCode()))) {
LoginActivity.show(this, new Bundle());
}
}
}
ViewModel にコンストラクターを追加したい場合は、そのファクトリ クラスを通じてViewModelProvider.Factoryを実装できます。
/**
* 创建viewModel
*/
public void createViewModel() {
if (mViewModel == null) {
Class modelClass;
Type type = getClass().getGenericSuperclass();
if (type instanceof ParameterizedType) {
modelClass = (Class) ((ParameterizedType) type).getActualTypeArguments()[0];
} else {
//如果没有指定泛型参数,则默认使用BaseViewModel
modelClass = BaseViewModel.class;
}
mViewModel = (VM) new ViewModelProvider(this).get(modelClass);
mViewModel.setBaseView(createBaseView());
}
}
ここで、setBaseView メソッドがアクティビティと ViewModel をバインドします。
protected BaseView createBaseView() {
return this;
}
ここの CustomProgressDialog.java は自分で書くことができます。グローバルにロードする箇条書きダイアログが
ここにあり、BaseActivity は基本的にカプセル化されています。次に、引き続き BaseFragment で ViewModel を参照します。同様に、一般的な形式でそれを導入します。
public abstract class BaseFragment<VM extends BaseViewModel, VDB extends ViewDataBinding> extends Fragment{
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container
, Bundle savedInstanceState) {
binding = DataBindingUtil.inflate(inflater, getLayoutId(), container, false);
mContentView = binding.getRoot();
createViewModel();
initView(mContentView, savedInstanceState);
return mContentView;
}
}
ここでの ViewModel オブジェクトの作成はアクティビティの場合と同じです
public void createViewModel() {
if (mViewModel == null) {
Class modelClass;
Type type = getClass().getGenericSuperclass();
if (type instanceof ParameterizedType) {
modelClass = (Class) ((ParameterizedType) type).getActualTypeArguments()[0];
} else {
//如果没有指定泛型参数,则默认使用BaseViewModel
modelClass = BaseViewModel.class;
}
mViewModel = (VM) new ViewModelProvider(this).get(modelClass);
mViewModel.setBaseView(createBaseView());
}
}
protected BaseView createBaseView(){
return this;
}
次に、BaseFragment に BaseView インターフェイス クラスを実装します。
public abstract class BaseFragment<VM extends BaseViewModel, VDB extends ViewDataBinding> extends Fragment implements BaseView {
protected Activity mActivity;
public CustomProgressDialog customProgressDialog;
protected VM mViewModel;
protected View mContentView;
protected VDB binding;
/**
* 获得全局的,防止使用getActivity()为空
*
* @param context
*/
@Override
public void onAttach(@NotNull Context context) {
super.onAttach(context);
this.mActivity = (Activity) context;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container
, Bundle savedInstanceState) {
binding = DataBindingUtil.inflate(inflater, getLayoutId(), container, false);
mContentView = binding.getRoot();
createViewModel();
initView(mContentView, savedInstanceState);
return mContentView;
}
public void createViewModel() {
if (mViewModel == null) {
Class modelClass;
Type type = getClass().getGenericSuperclass();
if (type instanceof ParameterizedType) {
modelClass = (Class) ((ParameterizedType) type).getActualTypeArguments()[0];
} else {
//如果没有指定泛型参数,则默认使用BaseViewModel
modelClass = BaseViewModel.class;
}
mViewModel = (VM) new ViewModelProvider(this).get(modelClass);
mViewModel.setBaseView(createBaseView());
}
}
protected BaseView createBaseView(){
return this;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initData(getArguments() == null ? new Bundle() : getArguments());
}
/**
* 该抽象方法就是 onCreateView中需要的layoutID
*
* @return
*/
protected abstract int getLayoutId();
/**
* 该抽象方法就是 初始化view
*
* @param view
* @param savedInstanceState
*/
protected abstract void initView(View view, Bundle savedInstanceState);
/**
* 执行数据的加载
*/
protected abstract void initData(Bundle bundle);
/**
* 关闭弹框
*/
private void closeLoadingDialog() {
if (customProgressDialog != null && customProgressDialog.isShowing()) {
customProgressDialog.dismiss();
}
}
/**
* 显示加载弹框
*
* @param dialogMessage 弹框内容,如果内容为空则不展示文字部分
*/
private void showLoadingDialog(String dialogMessage) {
if (customProgressDialog == null || !customProgressDialog.isShowing()) {
customProgressDialog = new CustomProgressDialog(getActivity());
customProgressDialog.isShowBg(StringUtil.isEmpty(dialogMessage));
customProgressDialog.setMessage(dialogMessage);
customProgressDialog.show();
}
}
@Override
public void showLoading(String dialogMessage) {
if (getActivity() != null && !getActivity().isFinishing()) {
getActivity().runOnUiThread(() -> showLoadingDialog(dialogMessage));
}
}
@Override
public void hideLoading() {
if (getActivity() != null && !getActivity().isFinishing()) {
getActivity().runOnUiThread(this::closeLoadingDialog);
}
}
@Override
public void refreshLoading(String dialogMessage) {
if (getActivity() != null && !getActivity().isFinishing()) {
getActivity().runOnUiThread(() -> {
if (customProgressDialog != null && customProgressDialog.isShowing()) {
customProgressDialog.setMessage(dialogMessage);
}
});
}
}
@Override
public void showToast(String msg) {
ToastUtils.showShort(getActivity(), msg);
}
@Override
public void onErrorCode(BaseModelEntity model) {
if (model != null && (UserAccountHelper.isLoginPast(model.getCode())||UserAccountHelper.isNoPermission(model.getCode()))) {
Bundle bundle = new Bundle();
LoginActivity.show(this, bundle);
}
}
}
このようにして、コードを簡単に書くことができます
public class TestActivity extends BaseActivity<MainViewModel, BaseFragmentContainerBinding> {
@Override
protected int getLayoutId() {
return R.layout.base_fragment_container;
}
@Override
public String setTitleBar() {
return "测试";
}
@Override
public void initView() {
}
@Override
public void initData(Bundle bundle) {
}
}
断片
public class TestFragment extends BaseFragment<TestViewModel, ActivityTestBinding> {
@Override
protected int getLayoutId() {
return R.layout.activity_test;
}
@Override
protected void initView(View view, Bundle savedInstanceState) {
}
@Override
protected void initData(Bundle bundle) {
binding.tvTest.setText("这是"+bundle.getInt(MainViewModel.ARG_PAGE)+"个页面");
}
}
最後に書いてありますが、デモは後でアップロードします、
ここでピットを踏むことに注意してください!!!基本クラスに他のジェネリックスを導入する場合は、ViewDataBinding と BaseViewModel の前ではなく、最後にジェネリックスを記述する必要がありますが、これは間違っています。
BaseActivity<T extends BeseBean,VM extends BaseViewModel, VDB extends ViewDataBinding>
正しいスペル
BaseActivity<VM extends BaseViewModel, VDB extends ViewDataBinding,T extends BeseBean>
今後もパッケージ化していきます
- BaseException を処理する統合例外エラー。
- ネットワークフレームワークRxjava2+Retrofitのカプセル化
- インターフェースデータ 統合データ
- アプリケーションおよび関連する API パラメーターの構成
- ツール クラスのカプセル化
ネットワーク リクエストと統合例外処理については、mvvm シンプル カプセル化に関するこのブログ投稿を確認してください(2)