精华内容
参与话题
问答
  • MVVM开发模式

    2021-01-09 16:50:08
    MVVM开发模式的主要目的和其他两种模式相同,都是为了分离模型和视图,主要有以下的优势: (1)低耦合 在MVVM模式中,当Model发生变化的时候View可以不变化,而当View发生变化的时候Model也可以不变,也就是View...

    MVVM开发模式的主要目的和其他两种模式相同,都是为了分离模型和视图,主要有以下的优势:
    (1)低耦合
    在MVVM模式中,当Model发生变化的时候View可以不变化,而当View发生变化的时候Model也可以不变,也就是View可以独立于Model修改和变化,同时同一个ViewModel可以绑定到多个不同的View上。
    (2)独立开发
    MVVM开发模式可以使设计人员和开发人员各司其职,设计人员可以集中精力进行页面元素的设计,开发工程师可以全身心投入业务逻辑的开发。
    (3)可重用
    MVVM开发模式中可以把一些视图逻辑放在ViewModel里面,让多个View来重用这些视图逻辑,从而提高页面性能和效率。
    (4)可测试
    在以前的MVC及MVP等传统开发模式中,界面测试是非常困难的工作,而在MVVM模式中测试可以专门针对ViewModel来写。

    展开全文
  • iOS OC - MVVM开发模式

    2020-06-19 15:32:21
    一个使用MVVM开发模式的小demo,里面注释写的已经很详细了,有哪里看不懂的小伙伴可以在评论区留言。
  • WPF的MVVM开发模式简单示例,详情见 https://blog.csdn.net/wf824284257/article/details/88758707
  • 简介: 一个浅封装、快速开发的 Android MVVM 开发框架 更多:作者提 Bug 标签: 上手特别容易,不会 MVVM 开发模式的都可以快速上手。 一个浅封装、快速开发的 Android MVVM 开发框架。 基于 Android ...

    FastAAC

    项目地址:ldlywt/FastAAC 

    简介: 一个浅封装、快速开发的 Android MVVM 开发框架

    更多:作者   提 Bug   

    标签:

     

    • 上手特别容易,不会 MVVM 开发模式的都可以快速上手。
    • 一个浅封装、快速开发的 Android MVVM 开发框架。
    • 基于 Android Architecture Components(AAC)。
    • 项目使用 Androidx 搭建。
    • 只使用官方部分的 MVVM 和 databind 的部分特性。

    Lib 结构

    image

    优点

    • 简单、浅封装、扩展性强

      代码简单,没有过度的封装,上手非常容易,Lib 只有十几个类。

      除了 Android 原生的依赖以外, 只集成了一个工具库 utilcodex,事件总线 live-event-bus,页面状态管理 loadsir, 状态栏沉浸式工具 immersionbar,并且都是可以插拔的,不需要替换即可。

      图片加载库,网络请求库等其他第三方 Lib 可根据个人兴趣自己选择集成即可。

    • 快速开发

      通过泛型可以减少很多不必要的重复代码,以前每个 Activity 都需要写如下重复代码,例如:

        ActivityMainBinding dataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
      
        MainVm mainVm = ViewModelProviders.of(this).get(MainVm.class);
      

      现在只需要在类名上面写上泛型即可,自动解析:

        public class MainActivity extends AbsMvvmActivity<MainVm, ActivityMainBinding> {}
      
    • 自动页面状态管理

      日常开发 Activity 的页面状态有:有网、无网络、空页面、loading 加载页面等各种页面。

      使用 LiveData 的监听集成在 BaseActivity 中,根据 BaseResult 返回的 code 来自动管理页面显示状态。

         switch (httpResult.getErrorCode()) {
                    case BaseResult.SUCCESS_CODE:
                        if (httpResult.getData() != null) {
                            resultCode = SuccessCallback.class;
                        } else {
                            resultCode = EmptyCallback.class;
                        }
                        break;
                    default:
                        resultCode = ErrorCallback.class;
                }
      

      如果想手动改变页面状态,只需在 ViewModel 中非常简单的设置,例如:

      无网络时:

        postPageState(new BaseResult(-1));
      

      数据为空时:

        public void clickNoData() {
            BaseResult<Object> baseResult = new BaseResult<>();
            baseResult.setErrorCode(0);
            baseResult.setData(null);
            postPageState(baseResult);
        }
      

    具体使用

    见 demo 中的 MainActivity。

    END

    大家有什么更好的建议请提出,一起学习进步。

    既然来了,麻烦动动手指,点个 star,非常感谢。

    License

    Copyright 2019 Wutao

    Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0
    展开全文
  • Demo采用Retrofit+RxJava+Okhttp网络请求,演示了JetPack中Navigation、LifeCycle+ViewModel+LiveData+Room+DataBinding+MVVM开发使用示例。
  • LPDMvvmKit 提供了一些常用的工具类,还有一些很轻巧的控件,以及最主要的是提供了MVVM开发框架,一直比较喜欢采用MVVM的框架来开发前端产品,所以会希望在iOS下也能找到类似的框架可以采用,但是一直没有找到合适的
  • MVVM开发模式DEMO

    2020-02-26 16:40:01
    用style框架 实现MVVM模式开发,逻辑清晰、便于理解,对于学习MVP模式有很大帮助!开发基于 vs2015 IDE
  • Android-MVVM开发模式应用 MVVM开发模式,是多种先进的开发思想集成在一起形成的一种高效率开发解决方案。 其中涉及到哪些开发思想呢? - MVC : 是一种把数据和视图分离解耦的思想,视图的展示由控制器进行分发...

    Android-MVVM开发模式应用

    CSDN:https://blog.csdn.net/chenzhen200638/article/details/82185190

    MVVM开发模式,是多种先进的开发思想集成在一起形成的一种高效率开发解决方案。
    其中涉及到哪些开发思想呢?
    - MVC : 是一种把数据和视图分离解耦的思想,视图的展示由控制器进行分发跳转;
    - DI : 依赖注入是指将组件的依赖通过外部以参数或其他形式注入。比如Dagger,就是依赖注入框架;
    - IOC : 控制反转,控制反转是将组件间的依赖关系从程序内部提到外部来管理;


    开始搭建mvvm开发框架,前提需要了解Dagger的使用。

    一、引入第三方库

    在Android的工程目录Gradle中加入以下库

    
    project.ext {
        retrofitVersion = "2.3.0"
        okhttpVersion = "3.9.0"
        supportVersion = "27.0.2"
        web3jVersion = "3.0.1-android"
        gethVersion = "1.7.0"
        gsonVersion = "2.8.2"
        rxJavaVersion = "2.1.6"
        rxAndroidVersion = "2.0.1"
        daggerVersion = "2.11"
    }
    
    dependencies {
        // Http client --网络库
        implementation "com.squareup.retrofit2:retrofit:$project.retrofitVersion"
        implementation "com.squareup.retrofit2:converter-gson:$project.retrofitVersion"
        implementation "com.squareup.retrofit2:adapter-rxjava2:$project.retrofitVersion"
        implementation "com.squareup.okhttp3:okhttp:$project.okhttpVersion"
        implementation "com.google.code.gson:gson:$project.gsonVersion"
    
        // RxJava 内存优化
        implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
        implementation 'com.jakewharton.rxbinding2:rxbinding-support-v4:2.1.1'
        implementation 'com.jakewharton.rxbinding2:rxbinding-appcompat-v7:2.1.1'
        implementation 'com.jakewharton.rxbinding2:rxbinding-design:2.1.1'
        implementation 'com.jakewharton.rxbinding2:rxbinding-recyclerview-v7:2.1.1'
        implementation 'com.jakewharton.rxbinding2:rxbinding-leanback-v17:2.1.1'
    
        // RxJava2.x
        implementation "io.reactivex.rxjava2:rxjava:$project.rxJavaVersion"
        implementation "io.reactivex.rxjava2:rxandroid:$project.rxAndroidVersion"
    
        // Lifecycle 生命周期
        implementation "android.arch.lifecycle:runtime:1.0.3"
        implementation "android.arch.lifecycle:extensions:1.0.0"
    
        // Dagger 2 DI依赖注入库
        // Dagger core
        implementation "com.google.dagger:dagger:$project.daggerVersion"
        annotationProcessor "com.google.dagger:dagger-compiler:$project.daggerVersion"
        // Dagger Android
        implementation "com.google.dagger:dagger-android-support:$project.daggerVersion"
        annotationProcessor "com.google.dagger:dagger-android-processor:$project.daggerVersion"
        // if you are not using support library, include this instead
        implementation "com.google.dagger:dagger-android:$project.daggerVersion"
    }
    

    现在我们来编写具体的业务代码,包的划分为 di,entity,service,viewmodle,ui几个目录
    - di: 依赖注入相关的代码
    - entity: 实体类
    - service: 网络请求,数据库相关代码
    - viewmodle: 业务逻辑代码
    - ui : activity界面视图相关代码

    二、编写Service数据源API

    //数据库操作代码,结合了RxJava2.x返回的都是Observeble对象;
    public class RealmService {
    
        public Single<List<Student>> findAllStudent() {
            return Single.fromCallable(() -> {
                final List<Student> students = new ArrayList<>();
                Realm realm = Realm.getDefaultInstance();
                try {
                    realm.executeTransaction(r -> {
                        RealmResults<Student> rs = realm.where(Student.class).findAll();
                        students.addAll(realm.copyFromRealm(rs));
                    });
                } catch (Exception ex) {
                    ex.printStackTrace();
                } finally {
                    if (realm != null) {
                        realm.close();
                    }
                }
                return students;
            });
        }
    
        public Completable addStudent(Student student) {
            return Completable.fromAction(() -> {
                Realm realm = Realm.getDefaultInstance();
                try {
                    realm.executeTransaction(r -> {
                        Student s = realm.createObject(Student.class,
                        UUID.randomUUID().toString());
                        s.setName(student.getName());
                        s.setAddress(student.getAddress());
                        s.setAge(student.getAge());
                        realm.copyFromRealm(s);
                    });
                } catch (Exception ex) {
                    ex.printStackTrace();
                } finally {
                    if (realm != null) {
                        realm.close();
                    }
                }
            });
    
    }

    定义实体类学生

    public class Student extends RealmObject {
        @PrimaryKey
        private String id;
        private String name;
        private String address;
        private int age;
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public String getId() {
            return id;
        }
    
        public String getName() {
            return name;
        }
    
        public String getAddress() {
            return address;
        }
    }

    三、编写ViewModle业务逻辑

    3.1 工厂类

    public class RealmServiceModelFactory implements ViewModelProvider.Factory  {
    
        private final RealmService mRealmService;
        @Inject
        public RealmServiceModelFactory(RealmService mRealmService) {
            this.mRealmService = mRealmService;
        }
    
        @NonNull
        @Override
        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
            return (T)new RealmServiceModel(mRealmService);
        }
    }

    3.2 业务逻辑的基类

    基类主要封装好通用的异常,进度条显隐控制逻辑;

    public class BaseViewModel extends ViewModel {
        protected final MutableLiveData<String> error = new MutableLiveData<>();
        protected final MutableLiveData<Boolean> progress = new MutableLiveData<>();
        protected Disposable disposable;
        @Override
        protected void onCleared() {
            if (disposable != null && !disposable.isDisposed()) {
                disposable.dispose();
            }
        }
    
        public LiveData<String> error() {
            return error;
        }
    
        public LiveData<Boolean> progress() {
            return progress;
        }
    
        protected void onError(Throwable throwable) {
            error.postValue(throwable.getMessage());
        }
    }

    3.3 业务逻辑Modle

    package realm.com.xn.realmdatabase.viewmodel;
    
    import android.arch.lifecycle.MutableLiveData;
    
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    import realm.com.xn.realmdatabase.entity.Student;
    import realm.com.xn.realmdatabase.service.RealmService;
    
    /**
     * Created by xn068074 on 2018/8/24.
     */
    
    public class RealmServiceModel extends BaseViewModel {
    
        private final RealmService mRealmService;
        private final MutableLiveData<List<Student>> studentsLiveData = new MutableLiveData<>();
    
        public RealmServiceModel(RealmService mRealmService) {
            this.mRealmService = mRealmService;
        }
    
        public MutableLiveData<List<Student>> students(){
            return this.studentsLiveData;
        }
    
        public void fetchAllStudent(){
            progress.postValue(true);
            mRealmService.findAllStudent()
                    .delay(2, TimeUnit.SECONDS)
                    .subscribe(students -> {
                         progress.postValue(false);
                         studentsLiveData.postValue(students);
                    });
        }
    
        public void addStudent(){
            this.progress.postValue(true);
    
            Student a = new Student();
            a.setAge(16);
            a.setAddress("中国上海");
            a.setName("陈永和");
    
            this.mRealmService.addStudent(a)
                    .delay(1,TimeUnit.SECONDS)
                    .subscribe(()->this.progress.postValue(false));
    
        }
    
        public void removeStudents(){
            this.progress.postValue(true);
            this.mRealmService.deleteAllStudent()
                    .delay(1,TimeUnit.SECONDS)
                    .subscribe(()->this.progress.postValue(false));
    
        }
    }
    

    3.4 类务工厂类

    这个类主要是用来生成modle的实例

    public class RealmServiceModelFactory implements ViewModelProvider.Factory  {
    
        private final RealmService mRealmService;
        @Inject
        public RealmServiceModelFactory(RealmService mRealmService) {
            this.mRealmService = mRealmService;
        }
    
        @NonNull
        @Override
        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
            return (T)new RealmServiceModel(mRealmService);
        }
    }

    四、UI界面

    在Activity中通过依赖注入调用业务逻辑类

    
    public class MVVMActivity extends AppCompatActivity implements OnClickListener {
    
        private TextView mask;
        private LinearLayout container;
    
        RealmServiceModel mRealmServiceModel;
    
        @Inject
        RealmServiceModelFactory mRealmServiceModelFactory;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            //这里是重点,需要注入
            AndroidInjection.inject(this);
    
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_vvm);
    
            mRealmServiceModel = ViewModelProviders.of(this,mRealmServiceModelFactory).get(RealmServiceModel.class);
    
            this.mask = this.findViewById(R.id.mask);
            this.container = this.findViewById(R.id.container);
    
            this.findViewById(R.id.query).setOnClickListener(this);
            this.findViewById(R.id.add).setOnClickListener(this);
            this.findViewById(R.id.clear).setOnClickListener(this);
    
            //进度条显示和隐藏
            mRealmServiceModel.progress().observe(this,this::progress);
            //异常信息提示
            mRealmServiceModel.error().observe(this,this::error);
            //学生数据更新
            mRealmServiceModel.students().observe(this,this::onStudentsChanged);
        }
    
        public void progress(boolean show){
            this.mask.setVisibility(show ? View.VISIBLE : View.GONE);
        }
    
        public void error(String error){
            Toast.makeText(this,error,Toast.LENGTH_LONG).show();
        }
    
        /**
         * 查询所有学生数据,并更新界面
         */
        public void onStudentsChanged(List<Student> students) {
            container.removeAllViews();
            for (Student s : students) {
                container.addView(buildTextView(s.toString()));
            }
        }
    
        public TextView buildTextView(String text) {
            TextView txt = new TextView(this);
            txt.setText(text);
            txt.setTextColor(Color.BLACK);
            txt.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
    
            LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            txt.setLayoutParams(lp);
            return txt;
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.add:
                    this.mRealmServiceModel.addStudent();
                    break;
                case R.id.query:
                    this.mRealmServiceModel.fetchAllStudent();
                    break;
                case R.id.clear:
                    this.mRealmServiceModel.removeStudents();
                    break;
            }
        }
    
    
    }
    

    五、依赖注入DI

    5.1 Module依赖注入

    
    @Module
    public class RealmServiceModule {
        @Provides
        public RealmServiceModelFactory provideRealmServiceModelFactory(RealmService realmService){
            return new RealmServiceModelFactory(realmService);
        }
    
        @Provides
        RealmService provideRealmService() {
            return new RealmService();
        }
    }

    5.2 BuildersModule

    这个主要是建立Activity和module的联系,是一个枢纽中心
    先定义一个通用的注解

        @Scope
        @Retention(RUNTIME)
        public @interface ActivityScope {
        }

    然后编写BuildersModule,建立Activity和Module的联系

    @Module
    public abstract class BuildersModule {
    
        @ActivityScope
        @ContributesAndroidInjector(modules = RealmServiceModule.class)
        abstract MVVMActivity bindMVVMActivityModule();
    
    }

    5.3 AppComponent

    这种写法是Dagger2的最新的用法,具体详情需要去了解Dagger2的使用了.

    @Singleton
    @Component(modules = {
            BuildersModule.class,
            AndroidSupportInjectionModule.class,
            RealmServiceModule.class })
    public interface AppComponent {
        @Component.Builder
        interface Builder {
            @BindsInstance
            Builder application(RealmApp app);
            AppComponent build();
        }
        void inject(RealmApp app);
    }

    5.4 Application

    最后一步要建立Activity生命周期和各个Module的关系,这样可以自动在onDestroy中销毁对象

    public class RealmApp extends Application implements HasActivityInjector {
    
        @Inject
        DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;
    
        @Override
        public void onCreate() {
            super.onCreate();
            //数据库相关的初始化
            Realm.init(this);
            RealmConfiguration configuration = new RealmConfiguration.Builder()
                    .name("realm.realm")
                    .schemaVersion(1)
                    .build();
            Realm.setDefaultConfiguration(configuration);
    
            //自动生成的DaggerAppComponent类,调用方法初始化
            DaggerAppComponent
                    .builder()
                    .application(this)
                    .build()
                    .inject(this);
    
        }
    
    
        @Override
        public AndroidInjector<Activity> activityInjector() {
            return dispatchingAndroidInjector;
        }
    
    }
    展开全文
  • Android MVVM 开发新姿势 一 1. 前言 网上有不少关于Android架构的讨论,如MVC, MVP,MVVM,最近还有MVI,emmm…不得不感慨时代变化太快。MVVM出来也有一段很长的时间了,接触时间不长,写一篇文章记录一下。同时也...

    Android MVVM 开发新姿势 一

    1. 前言

    网上有不少关于Android架构的讨论,如MVC, MVP,MVVM,最近还有MVI,emmm…不得不感慨时代变化太快。MVVM出来也有一段很长的时间了,接触时间不长,写一篇文章记录一下。同时也作为一个思路,抛砖引玉。

    2. MVVM概略

    首先,要了解一个架构思想那么首先要看一下相关文章,其中又以谷歌为佳,下面就是MVVM(Model-View-ViewModel)结构的架构图。
    相关链接:https://developer.android.google.cn/jetpack
    MVVM(Model-View-ViewModel)结构的架构图
    简单介绍一下各个模块:

    View层 绿色框中的Activity/Fragment,继承至LifecycleActivity\LifecycleFragment,是UI控件的宿主。
    核心职责是:
    更新UI控件显示,包括状态及数据,由ViewModel驱动
    监听UI事件及其生命周期,驱动ViewModel
    View层不直接处理任何业务逻辑及数据加工。尽量做到瘦身,代码逻辑简约,减轻UI线程负担。

    ViewModel层 蓝色框的ViewModel。只做业务逻辑操作,不持有任何UI控件的引用。那数据的更新如何通知到View层,这就要仰仗LiveData,具体使用后面会提及。

    Model层 橘黄色框的Repository及其下都是Model层。Model层就是数据层。数据来源有:
    本地存储数据,如数据库,文件,SharedPreferences(本质也是文件)
    内存的缓存或临时数据
    通过各种网络协议获取的远程数据

    Repository是数据仓库,整合各路来源的数据,再统一暴露给ViewModel层使用。官方新框架在这一层只提供给了一个新的SQLite数据库封装类库Room,这是可选的。换言之,Model层,官方只提供指导思想,并未有具体实现方案。也就是可以自由发挥,各种嗨,Emm

    各个层次的依赖如图:
    依赖

    3. 框架搭建

    首先解决一下依赖最底层model的问题。
    一般而言,model一般用于从数据源获取数据。当然也可以从本地获取数据
    数据源一般就是后台服务器。
    我们抽象一下,抽出来就是一个抽象类。

    public abstract class BaseModel {
    
        public void getData(int code, BaseSubscriber subscriber , Object... parameter){
            //TODO 调用网络请求前的操作
            requestInNet(code, subscriber ,parameter);
        }
    
        /**
         * 网络请求
         * @param code 请求对应的code用于区分不同的请求
         * @param subscriber 回调
         * @param parameter 可变参数列表 存放请求所需参数
         */
        protected abstract void requestInNet(int code,BaseSubscriber subscriber ,Object... parameter);
    }
    
    

    接下来需要思考一个问题,下层不存在上层依赖,那么viewmodel和model之间该怎么通讯呢?思索一番,决定用rxjava的回调。Emmm,那么肯定要根据需求改造一番。代码如下:

    public abstract class BaseSubscriber<T> extends ResourceSubscriber<T> {
        protected BaseViewModel vm;
    
        public BaseSubscriber(BaseViewModel vm) {
            this(vm, null);
        }
        public BaseSubscriber(BaseViewModel vm, @Nullable String requestKey) {
            this.vm = vm;
            this.vm.subscribe(this, requestKey);
        }
    
        @Override
        public void onStart() {
            super.onStart();
            //TODO 此处可以判断网络,无网络调用onStartOffline
            onStartRequest();
        }
    
        @Override
        public void onNext(T t) {
            onSuccess(t);
        }
    
        /**
         * 请求失败
         * 可重写复用
         */
        @Override
        public void onError(Throwable t) {
            vm.onError(t);
        }
    
        /**
         * 完成时回调
         */
        @Override
        public abstract void onComplete();
    
        /**
         * 当开始请求时没有网络
         * 可重写复用
         */
        public void onStartOffline(){
    
        }
    
        /**
         * 当开始请求时时
         * 可重写复用
         */
        public void onStartRequest(){
    
        }
    
        /**
         * 当成功返回时
         * @param t 返回的数据
         */
        public abstract void onSuccess(T t);
    }
    

    回调改造完成,那么我们就写一个viewmodel。

    public abstract class BaseViewModel<M extends BaseModel> extends AndroidViewModel {
        /* RX相关注册 */
        /**
         * 一次性容器,可以容纳多个其他一次性用品和提供I/O添加和移除复杂性。
         */
        private CompositeDisposable mCompositeDisposable;
        private ArrayMap<String, Disposable> mDisposableMap;
    
        protected M model;
    
        protected final MutableLiveData<Intent> startIntent = new MutableLiveData<>();
    
        protected final MutableLiveData<ArrayList<Object>> messageToContext = new MutableLiveData<>();
    
        public BaseViewModel(Application application){
            super(application);
            model = setModel();
        }
    
        /**
         * 设置model
         * @return model
         */
        protected abstract M setModel();
    
        protected void getData(int code , BaseSubscriber subscriber , Object... param){
            if (model == null){
                throw new NullPointerException("进行获取数据的操作前,检查Model是否赋值");
            }
            model.getData(code,subscriber,param);
        }
    
        protected void sendMessageToContext(ArrayList<Object> params){
            messageToContext.setValue(params);
        }
    
        /**
         * 注册RX可处理的线程
         * @param disposable 可处理的线程
         * @param requestKey 请求键
         */
        public void subscribe(Disposable disposable, @Nullable String requestKey) {
            if (null == mCompositeDisposable) {
                mCompositeDisposable = new CompositeDisposable();
            }
            mCompositeDisposable.add(disposable);
    
            if (null == mDisposableMap){
                mDisposableMap = new ArrayMap<>();
            }
            if (!TextUtils.isEmpty(requestKey)){
                mDisposableMap.put(requestKey, disposable);
            }
        }
    
        /**
         * 注销所有线程
         */
        public void unsubscribe() {
            if (null != mCompositeDisposable) {
                mCompositeDisposable.clear();
            }
        }
    
        /**
         * 移除线程
         * @param requestKey 请求键
         */
        public void removeDisposable(@NotNull String requestKey) {
            if (null != mCompositeDisposable && null != mDisposableMap
                    && mDisposableMap.containsKey(requestKey)) {
                mCompositeDisposable.remove(mDisposableMap.get(requestKey));
                mDisposableMap.remove(requestKey);
            }
        }
    
        /**
         * 请求时客户端错误处理
         */
        @CallSuper
        public void onError(Throwable throwable) {
            throwable.printStackTrace();
            // 当在主线程时显示异常Toast
            if (Looper.getMainLooper() == Looper.myLooper()) {
                //TODO 后面添加
            }
        }
    
    }
    

    最后搞定activity

    public abstract class BaseMvvmActivity <VM extends BaseViewModel,VDB extends
            ViewDataBinding> extends AppCompatActivity {
            
        protected VDB binding;
        protected VM viewModel;
    
        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            viewModel = setViewModel();
            doBeforeBinding();
            onBinding();
            initUI();
            setDefaultObservers();
        }
    
        protected void setDefaultObservers() {
        }
    
        /**
         * 设置布局文件id
         * @return  layout id
         */
        protected abstract int getLayoutId();
    
        protected void doBeforeBinding(){}
    
        protected void onBinding(){
            binding = DataBindingUtil.setContentView(this, getLayoutId());
            binding.setLifecycleOwner(this);
            binding.setVariable(BR.viewModel,viewModel);
        }
    
        /**
         * 设置ViewModel
         * @return viewModel
         */
        protected abstract VM setViewModel();
    
        /**
         * 初始化ui的方法
         */
        protected abstract void initUI();
    
        public void changeIntoLightStatusBar(boolean isLight){
            if (isLight){
                getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
            }else{
                getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            }
        }
    }
    

    4. 实现简单功能

    网络加载一张图片&获取一段数据显示
    首先图片加载库glide,
    配置glide balabala…此处省略1000字
    然后新建一个类,ViewUtils 名字随意呀

    public class ViewUtils {
    
        @BindingAdapter({"imageUrl"})
        public static void loadImageOnTheInternet(final ImageView imageView, final String url) {
            if (null != url && url.startsWith("http")) {
                imageView.post(() ->
                    Glide.with(imageView.getContext()).load(url).into(imageView));
            }
        }
    }
    

    图片加载搞定了,下面是网络数据加载
    同样省略1000字

    public class NetworkClient {
    
        private static Retrofit retrofit;
        private static final int TIME_OUT = 60*5;
    
        /**
         * 私有化构造方法
         */
        private NetworkClient(){
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(message -> LogUtil.i("HttpLog",message));
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    
            OkHttpClient okHttpClient = new OkHttpClient()
                    .newBuilder()
                    .connectTimeout(TIME_OUT, TimeUnit.SECONDS)
                    .readTimeout(TIME_OUT, TimeUnit.SECONDS)
                    .addInterceptor(loggingInterceptor)
                    .build();
            retrofit = new Retrofit.Builder()
                    .baseUrl(Constant.BASE_URL)
                    .client(okHttpClient)
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .build();
        }
    
        private static class SingletonHolder{
            private static final NetworkClient INSTANCE = new NetworkClient();
        }
    
        public static NetworkClient getNetworkClient (){
            return SingletonHolder.INSTANCE;
        }
    
        /**
         * 获取api
         * @param service
         * @param <T>
         * @return
         */
        public <T> T createApi(Class<T> service){
            return retrofit.create(service);
        }
    
    }
    
    public interface UserApi {
    
        /**
         * 测试,获取公众号列表
         * @return
         */
        @GET("wxarticle/chapters/json")
        Flowable<ResponseBean<ArrayList<PublicNumBean>>> wxarticle();
    }
    

    关键代码如上。
    下面前期准备工作都搞定了,我们开始写布局

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:tools="http://schemas.android.com/tools"
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto">
    
        <data>
            <import type="android.view.View"/>
            <import type="java.lang.String"/>
            <variable
                    name="viewModel"
                    type="com.tao.androidx_mvvm.viewmodel.ViewModelOfMain"/>
        </data>
    
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context=".activity.MainActivity">
    
            <Button
                android:id="@+id/text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{viewModel.text}"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                android:onClick="@{(view)->viewModel.onClick(view)}"/>
    
            <ImageView
                app:layout_constraintTop_toBottomOf="@id/text"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:imageUrl="@{viewModel.text}"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
    
        </androidx.constraintlayout.widget.ConstraintLayout>
    </layout>
    

    一个button一个imageView搞定
    ViewModel

    public class ViewModelOfMain extends BaseViewModel<ModelOfMain> {
    
        public final MutableLiveData<String> text = new MutableLiveData<>();
    
        public ViewModelOfMain(Application application) {
            super(application);
            text.setValue("Hello");
        }
    
        public void getData(){
            getData(TEXT, new BaseSubscriber(this) {
                @Override
                public void onComplete() {
    
                }
    
                @Override
                public void onSuccess(Object o) {
                    LogUtil.i("ViewModelOfMain",o.toString());
                    text.setValue(o.toString());
                }
    
                @Override
                public void onError(Throwable t) {
                    super.onError(t);
                    LogUtil.i("ViewModelOfMain",t.getMessage());
                }
            });
        }
    
        @Override
        protected ModelOfMain setModel() {
            return new ModelOfMain();
        }
    
        public void onClick(View v){
            if (v.getId() == R.id.text){
               getData();
            }
        }
    }
    

    Model:

    public class ModelOfMain extends BaseModel {
    
        public static final int TEXT = 1001;
    
        @Override
        protected void requestInNet(int code, BaseSubscriber subscriber, Object... parameter) {
            switch (code) {
                case TEXT:
                    LogUtil.i("ModelOfMain", "requestInNet");
                    NetworkClient.getNetworkClient().createApi(UserApi.class)
                            .wxarticle()
                            .subscribeOn(Schedulers.io())
                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribe(subscriber);
                    break;
                default:
                    LogUtil.i("ModelOfMain", "default");
                    break;
            }
        }
    }
    

    Ativity:

    class MainActivity : BaseMvvmActivity<ViewModelOfMain,ActivityMainBinding>() {
        override fun setViewModel(): ViewModelOfMain {
            return ViewModelOfMain(application)
        }
        
        override fun initUI() {
            viewModel.text.value = "http://img5.imgtn.bdimg.com/it/u=3300305952,1328708913&fm=26&gp=0.jpg"
        }
        
        override fun getLayoutId(): Int {
            return R.layout.activity_main
        }
    
    }
    

    简单效果就如上面一样。
    关于recyclerview,fragment,dialog的使用就下次再写。

    github:https://github.com/huangtaoOO/AndroidXMVVM
    接口:https://www.wanandroid.com/

    展开全文
  • WPF MVVM开发框架

    2018-03-20 12:55:54
    WPF编写的MVVM框架,可以拿来直接修改成自己的项目(框架比较基础,但大部分功能已经可以实现)
  • android MVVM开发模式(一)

    千次阅读 2016-07-22 12:04:44
    android MVVM开发模式 概念 mvvm 是一个在 mvp 架构上修改,目标是将view的一些更改,跟model关联起来,使得model的数据改变,直接通知到view上面来,从而解决mvp架构里面的v-p之间的接口太重问题。 所以mvvm的...
  • android MVVM开发模式(三) 为了更好地理解@BindingAdapter,github地址里面提交了一个adapters目录,将系统提供的适配提交上去,以便查阅。回顾 我们前两节讲了哪些内容呢? mvvm模型概念 dataBinding是什么 ...
  • MVC、MVP和MVVM开发模式对比1.MVC(Model View Controller)模式2.MVP(Model View Presenter)模式3.MVVM(Model View ViewModel)模式 1.MVC(Model View Controller)模式 MVC架构模式为,用户操作—>View(接收用户的...
  • 介绍 在学习jetpack之后,了解navigation组件,navigation...建议使用该组件学习MVVM开发模式,MVVM开发模式就是基于jetpack框架,使用livedata+viewmodel+databinding开发 navigation开发步骤 建立Activity,进入A
  • SilverLight在MVVM开发模式下对MySQL数据库操作源码,VS2012+silverLight5
  • 本文主要是翻译Rachel Lim的一篇有关MVVM模式介绍的博文A Simple ...在我看来,如果你使用的是WPF或Sliverlight来开发程序就应该使用MVVM设计模式。它是你的代码清晰明了并易于维护。 可问题是网上有很多有关MVVM...
  • MVVM开发模式实例解析

    万次阅读 2013-01-14 09:54:25
    此实例为本人依托网上原有资料,加以个人理解整合,在MVVM模式下写的一个基于MySQL数据库的小Demo,...MVVM开发模式 概述 MVVM(Model-View-ViewModel)是在WPF/Silverlight一种很常见的开发模式,是MVC模式的一种变
  • mvvm开发模式

    2019-02-25 18:23:18
    MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致。唯一的区别是,它采用双向绑定(data-binding):View的变动,自动反映在 ViewModel,反之亦然。Angular 和 Ember 都采用这种模式。 说明...
  • android MVVM开发框架——(1)DataBinding 基础应用android MVVM开发框架——(2)DataBinding 应用于ListView如果你对mvvm或者databinding不太熟悉的,建议先去看看前两篇博文
  • 在WinForm程序中使用MVVM开发模式

    千次阅读 2016-12-09 15:45:53
    在WinForm程序中使用MVVM开发模式 熟悉WPF的朋友一定在WPF程序中使用了MVVM的开发模式,因为MVVM可以带来以下几个优点: 1. 低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View...
  • 安卓Kotlin+组件化+MVVM开发项目基础搭建 1.commen 公共业务 供上层业务调用 2.home | user 首页和个人中心模块 3. isDebug, true-home模块可进行单独编译 ,false- 所有模块融合到app模块 项目地址:...
  • android MVVM开发框架——(1)DataBinding 基础应用 附上mvvm中databinding的基本应用链接,只有找到了基本用法才能继续进阶
  • sanic+mvvm开发案例

    2018-01-22 09:49:02
    最近在学习sanic的开发,从网上找到了一个不错的案例,所以放来给大家参考
  • 使用它我们可以轻松实现MVVM(模型-视图-视图模型)模式,来实现应用之间数据与视图的分离、视图与业务逻辑的分离、数据与业务逻辑的分离,从而达到低耦合、可重用性、易测试性等好处。而使用DataBinding不仅减少了...
  • iOS OC mvvm开发模式

    2020-06-19 16:28:36
    相信大家对MVC开发都已经不陌生了,最经典开发模式 MVC构成: M:model也就是数据模型 V:View视图 C:Controller控制器 Model和View是相互独立的。View只负责页面展示,Model只是数据的存储,那么也就达到...
  • Android之MVVM开发模式

    2018-12-06 14:26:00
    MVVM 模式简介 MVVM模式是指Model-View-ViewModel。相信看过笔者关于MVP的文章的读者也会发现,无论如何抽象化,在我们的View层中是无法避免的要处理一部分逻辑的。而MVVM模式中的View是将View的状态和行为完全...
  • 理解javascript中的MVVM开发模式  http://blog.csdn.net/slalx/article/details/7856769 MVVM的全称是Model View ViewModel,这种架构模式最初是由微软的MartinFowler作为微软软件的展现层设计模式的规范提出,...
  • MVVM模式就不细说了 个人理解 M是Model,是业务实体model,包含了数据的存取访问 V是View,是页面,是展示,是数据的显示,应该是单纯的xaml代码 VM是ViewModel,他应该是View上数据,方法,事件的抽象集合,是...

空空如也

1 2 3 4 5 ... 20
收藏数 6,261
精华内容 2,504
关键字:

mvvm开发