MVVM设计模式

MVVM设计模式

在介绍MVVM设计模式之前我们先介绍一下DataBinding

DataBinding,2015年IO大会介绍的一个框架,字面理解即为数据绑定,是Google对MVVM在Android上的一种实现,可以直接绑定数据到xml中,并实现自动刷新。

好处:

  • 去掉大部分UI相关代码(比如findViewById、setOnClickListener、setText等)
  • xml变成UI的唯一真实来源,数据绑定也直接发生在xml

首先我们要在build.gradle(app)的android里添加

  dataBinding {
        enabled = true
    }

然后我们在Activity创建的layout里面添加 两个标签



    

        
    


    



我们先用layout包围

  • 注意我们在data里面声明了一个变量 他是 com.example.andy.mvvmtest.bean的变量
  • 然后我们在Textview里面设置text使用了bean这个变量的name属性

这是我bean的代码

public class bean {
    public  String name;

    public bean(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

这就是一个普通的javabean

接着 我们在MianActivity使用DataBindUtil来setContentView
然后系统会自动生成一个layout名对应的Binding如activity_main 则生成了AcitivityMianBinding
然后我们使用这个Binding来setTextview对应的bean

public class MainActivity extends AppCompatActivity {
    ActivityMainBinding binding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding=DataBindingUtil.setContentView(this,R.layout.activity_main);
        bean bean1=new bean("hhhhhh");
        binding.setBean(bean1);
        bean1.setName("asdfasdf");
    }
}

这样我们就完成了dataBindin入门

接下来我们说一下MVVM模式


MVVM设计模式_第1张图片
image
  • Modle即dataModle为抽象数据源为VIewModle提供数据
  • 即通知viewModle响应事件
  • 提供View显示的数据流

这个是基本效果

MVVM设计模式_第2张图片
MVVMTest.gif

我们先判断登录的密码和用户名 达到条件后就使用Retrofit请求 然后得到一个刷新列表。

我们先来展示一下基本MVVM模式的代码
首先我们定义一个ViewModle接口


public interface ViewModle {
    public void destroy();
}

这里只定义一个destory的接口

这是MainActivity的layout



    

        
    


    
    
    

我们先来实现以下MainViewModle

public class MainVIewModle implements ViewModle {
    private static final String TAG = "MainVIewModle";
    public ObservableField name;
    public ObservableField password;
    public ObservableInt nameVisiable;
    public ObservableInt pswVisiable;
    public ObservableInt buttonVisiable;
    public ObservableBoolean buttonEnable;
    public ObservableInt recycleVisiable;
    private Context context;
    private DataListner listner;
    private Disposable disposable;


    public MainVIewModle(Context context, DataListner listner) {
        this.context = context;
        this.listner = listner;
        nameVisiable = new ObservableInt(View.VISIBLE);
        pswVisiable = new ObservableInt(View.VISIBLE);
        buttonVisiable = new ObservableInt(View.VISIBLE);
        recycleVisiable = new ObservableInt(View.GONE);
        password = new ObservableField<>("");
        name = new ObservableField<>("");
        buttonEnable = new ObservableBoolean(false);

    }

    @Override
    public void destroy() {
        context = null;
        listner = null;
        if(disposable!=null)
        disposable.dispose();
    }

    interface DataListner {
        public void OndateChage(List list);
    }

    public TextWatcher getnameTextWatcher() {
        return 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) {
                Log.d(TAG, "onTextChanged: " + " " + s.length() + password.get().length());
                if (s.length() > 4 && password.get().length() > 7)
                    buttonEnable.set(true);
                else
                    buttonEnable.set(false);
            }

            @Override
            public void afterTextChanged(Editable s) {
                name.set(s.toString());
            }
        };
    }

    public TextWatcher getpswTextWatcher() {
        return 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) {
                Log.d(TAG, "onTextChanged: " + s.length() + " " + name.get().length());
                if (s.length() > 7 && name.get().length() > 4)
                    buttonEnable.set(true);
                else
                    buttonEnable.set(false);
            }

            @Override
            public void afterTextChanged(Editable s) {
                password.set(s.toString());
            }
        };
    }

    public void OnclickChange(View view) {

        Log.d(TAG, "OnclickChange: " + view.getId());
        Toast.makeText(view.getContext(), "hhhhh", Toast.LENGTH_SHORT).show();
        login();
    }

    public void login() {
        User user = new User();
        user.setName(name.get());
        user.setPassword(password.get());
        recycleVisiable.set(View.VISIBLE);
        nameVisiable.set(View.GONE);
        pswVisiable.set(View.GONE);
        buttonVisiable.set(View.GONE);
        LoginService service = LoginService.Factory.create();
        service.dologin(user)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(new Observer>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        disposable=d;
                    }

                    @Override
                    public void onNext(List value) {

                    }

                    @Override
                    public void onError(Throwable e) {
                        List list=new ArrayList();
                        for(int i=0;i<10;i++)
                        {
                            ListBean bean=new ListBean();
                            bean.setTitle("On The NO"+i);
                            bean.setSummary("This is No"+i+"News");
                            bean.setWatchers(10+i);
                            bean.setForks(5+i);
                            bean.setForks(3+i);
                            list.add(bean);
                        }
                        listner.OndateChage(list);
                    }

                    @Override
                    public void onComplete() {

                    }
                });
        List list=new ArrayList();
                        for(int i=0;i<10;i++)
                        {
                            ListBean bean=new ListBean();
                            bean.setTitle("On The NO"+i);
                            bean.setSummary("This Is No"+i+"News");
                            bean.setWatchers(10+i);
                            bean.setForks(5+i);
                            bean.setForks(3+i);
                            list.add(bean);
                        }
                        listner.OndateChage(list);

    }
}

这里的getnameTextWatcher 和 getpswTextWatcher 与上面的layout相对应 分别判断 这里的密码和用户名是否符合要求,符合则将 登录的button 设为可以点击 login就是执行登录操作。然后我们要在desotry哪里将 disposable.dispose();防止页面被销毁 时候还在请求。

下面在看一下我们的modle

public class User {
    public String name;
    public String password;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

modle 只有两个简单的参数

public interface LoginService {
    @FormUrlEncoded
    @POST("users/{username}/repos")
    Observable> dologin(@Body User username);


    class Factory {
        public static LoginService create() {
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http://192.168.0.1:8080/")
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
            return retrofit.create(LoginService.class);
        }
    }
}

MainActivity

public class MainActivity extends AppCompatActivity implements MainVIewModle.DataListner{
    public volatile int a=1;
    private static final String TAG="MainActivity";
    ActivityMainBinding binding;
    Handler h;
    MyAdapter myAdapter;
    MainVIewModle mainVIewModle;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding=DataBindingUtil.setContentView(this,R.layout.activity_main);
        mainVIewModle= new MainVIewModle(this,this);
        bean bean1=new bean(new ObservableField("JJJJJJ"));
        binding.setBean(mainVIewModle);
        myAdapter=new MyAdapter();
        binding.recycleview.setAdapter(myAdapter);
        binding.recycleview.setLayoutManager(new LinearLayoutManager(this));
    }


    @Override
    public void OndateChage(List list) {
        myAdapter.setList(list);
        myAdapter.notifyDataSetChanged();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mainVIewModle.destroy();
    }
}

在MainActivity里面我们只需要初始化Recycleview的Adapter和在Destory的时候调用MainVIewModle的Dstory

这个是RecycleView的Item 和Activity_main差不多 就不展开说了。



    

        
    

    

        

            

            

            

            

                

                

                

            

        

    



下面是RecycleView的Adapter

public class MyAdapter extends RecyclerView.Adapter {
    List mylist;
    public MyAdapter()
    {
        mylist= Collections.emptyList();
    }
    public void MyAdapter(List list)
    {
        this.mylist=list;
    }
    public void setList(List list)
    {
        this.mylist=list;
    }
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
      RecycleviewItemBinding binding= DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),R.layout.recycleview_item,parent,false);

        return new MyViewHolder(binding);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.bindRepository(mylist.get(position));
    }

    @Override
    public int getItemCount() {
        return mylist.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder{

        final RecycleviewItemBinding binding;

        public MyViewHolder(RecycleviewItemBinding binding) {
            super(binding.cardView);
            this.binding = binding;
        }
        void bindRepository(ListBean repository) {
            if (binding.getViewModel() == null) {
                binding.setViewModel(new ItemVIewModle(itemView.getContext(), repository));
            } else {
                binding.getViewModel().setListBean(repository);
            }
        }
    }

}

我们的ViewHolder并不是使用Itemview来findViewById 而是直接传入一个Binding然后在bindRepository里面绑定数据,假如这个Item已经创建 那么直接set那个bean

这个是RecycleView的ViewModle

public class ItemVIewModle extends BaseObservable implements ViewModle {
    private Context context;
    private ListBean bean;
    public ItemVIewModle(Context context, ListBean repository) {
        this.context=context;
        this.bean=repository;
    }

    @Override
    public void destroy() {

    }
    public void setListBean(ListBean bean)
    {

    }
    public String getTitle()
    {
        if(bean!=null)
            return bean.getTitle();
        else
            return "";
    }
    public String getSummary()
    {
        if(bean!=null)
            return bean.getSummary();
        else
            return "";
    }
    public String getWatchers()
    {
        if(bean!=null)
            return bean.getWatchers()+"";
        else
            return "";
    }
    public String getStars()
    {
        if(bean!=null)
            return bean.getStars()+"";
        else
            return "";
    }
    public String getForks()
    {
        if(bean!=null)
            return bean.getForks()+"";
        else
            return "";
    }
    public void onItemClick(View view)
    {

    }
}

这个和layout是对应的

这个是listItem的Modle

public class ListBean implements Parcelable {
    private String Title;
    private String Summary;
    private int watchers;
    private int  stars;
    private int forks;
    public void onItemClick(View view)
    {

    }

    public String getTitle() {
        return Title;
    }

    public void setTitle(String title) {
        Title = title;
    }

    public String getSummary() {
        return Summary;
    }

    public void setSummary(String summary) {
        Summary = summary;
    }

    public int getWatchers() {
        return watchers;
    }

    public void setWatchers(int watchers) {
        this.watchers = watchers;
    }

    public int getStars() {
        return stars;
    }

    public void setStars(int stars) {
        this.stars = stars;
    }

    public int getForks() {
        return forks;
    }

    public void setForks(int forks) {
        this.forks = forks;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.Title);
        dest.writeString(this.Summary);
        dest.writeInt(this.watchers);
        dest.writeInt(this.stars);
        dest.writeInt(this.forks);
    }

    public ListBean() {
    }

    protected ListBean(Parcel in) {
        this.Title = in.readString();
        this.Summary = in.readString();
        this.watchers = in.readInt();
        this.stars = in.readInt();
        this.forks = in.readInt();
    }

    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        @Override
        public ListBean createFromParcel(Parcel source) {
            return new ListBean(source);
        }

        @Override
        public ListBean[] newArray(int size) {
            return new ListBean[size];
        }
    };
}

这样我们就完成了基本的MVVM模式框架,MVVM框架现对于MVP是不是省了好多代码呢。

你可能感兴趣的:(MVVM设计模式)