Android项目mvvm的尝试
五一期间没事,继续研究最近也使用得比较多的Android,很多Activity代码上百成千行,这次使用MVVM的方式,将部分代码分到别地方,也就是ViewModel。
1、首先导Jetpack包,这个包基本用kotlin语言更好点,毕竟可以用协程。
//jetpack def lifecycle_version = "2.2.0" implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
2、新建一个容器类,这个是官方推荐的,我觉得有点像逻辑层,不管了,先建吧 SystRepository.class,把逻辑全写在里面
实现功能比较简单,从网络获取用户信息。
public class SysRepository { private Context context; private IUserService userService; public SysRepository(Context context) { this.context = context; userService = RetrofitClient.getInstance().getService(IUserService.class); } public void userBinder(MutableLiveDatauserId,MutableLiveData userName){ String spuserId = ""; UserLoginInfo userLoginInfo = SpHelper.GetUserLoginSetting(context); if(userLoginInfo!=null){ spuserId = userLoginInfo.getUserId(); } Call > call = userService.getUserInfo(spuserId); call.enqueue(new Callback >() { @Override public void onResponse(Call > call, Response > response) { if(response.isSuccessful()) { ResultBean resultBean = response.body(); if (resultBean.getSuccess()) { UserInfoBean userInfoBean = resultBean.getResult(); if (userInfoBean != null) { userId.postValue(userInfoBean.getUserId()); userName.postValue(userInfoBean.getUserName()); } } else { Toast.makeText(context, resultBean.getMsg(), Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(context,response.message() , Toast.LENGTH_SHORT).show(); } } @Override public void onFailure(Call > call, Throwable t) { Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show(); } }); } }
3、新建viewModel文件,这地方要注意的是,如果用到Context需要继承AndroidViewModel,官方推荐是不要传这个,正常是继承ViewModel
public class SysViewModel extends AndroidViewModel { private MutableLiveDatauserId; private MutableLiveData userName; private static final String TAG = SysViewModel.class.getSimpleName(); private SysRepository sysRepository; private Context context; public SysViewModel(@NonNull Application application) { super(application); this.context = application; sysRepository = new SysRepository(this.context); } public MutableLiveData getUserId() { if(userId==null){ userId = new MutableLiveData<>(); userId.setValue(""); } return userId; } public MutableLiveData getUserName() { if(userName==null){ userName = new MutableLiveData<>(); userName.setValue(""); } return userName; } public void userInfoBinder(){ sysRepository.userBinder(userId,userName); } }
下面就是在主界面中修改了,一种是在Fragment的写法,一种是Activity中的写法。
//Fragment写法 binding = DataBindingUtil.inflate(inflater,R.layout.fragment_sys,container,false); //Activity //binding = DataBindingUtil.setContentView(this,R.layout.fragment_sys); sysViewModel = new ViewModelProvider(getActivity(),new ViewModelProvider.AndroidViewModelFactory(getActivity().getApplication())).get(SysViewModel.class); binding.setSysViewModel(sysViewModel); binding.setLifecycleOwner(getActivity()); View view = binding.getRoot(); return view;
下面的文字是以前的写法,包括非bind的写法,不一定对,可以,留着参考
一、非bind方式
1、Fragment文件添加代码
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View view = inflater.inflate(R.layout.fragment_sys, container, false); userViewModel = new UserViewModel(getActivity()); sys_fra_tv_username = view.findViewById(R.id.sys_fra_tv_username); sys_fra_tv_userid = view.findViewById(R.id.sys_fra_tv_userid); userViewModel.getUserId().observe(getActivity(), new Observer() { @Override public void onChanged(String s) { sys_fra_tv_userid.setText(s); } }); userViewModel.getUserName().observe(getActivity(), new Observer () { @Override public void onChanged(String s) { sys_fra_tv_username.setText(s); } }); return view; }
2、使用了观察者模式来监听数据的变化,在合适的地方加上
public class SysViewModel extends AndroidViewModel { private MutableLiveDatauserId; private MutableLiveData userName; private static final String TAG = SysViewModel.class.getSimpleName(); private SysRepository sysRepository; private Context context; public SysViewModel(@NonNull Application application) { super(application); this.context = application.getBaseContext(); sysRepository = new SysRepository(this.context); } public MutableLiveData getUserId() { if(userId==null){ userId = new MutableLiveData<>(); userId.setValue(""); } return userId; } public MutableLiveData getUserName() { if(userName==null){ userName = new MutableLiveData<>(); userName.setValue(""); } return userName; } public void userInfoBinder(){ sysRepository.userBinder(userId,userName); } }
3、布局文件如下
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/gray_f0f0f0" android:orientation="vertical" tools:context="com.yysoft.syjz.Fragments.SysFragment"> <LinearLayout android:layout_width="match_parent" android:layout_height="80dp" android:layout_marginLeft="10dp" android:layout_marginTop="20dp" android:layout_marginRight="10dp" android:background="@color/white" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginLeft="10dp" android:gravity="center" android:text="用户Id:" android:textColor="@color/text_9f9f9f" android:textSize="24sp" /> <TextView android:id="@+id/sys_fra_tv_userid" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginLeft="10dp" android:gravity="center" android:textColor="@color/text_9f9f9f" android:textSize="24sp" /> LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="80dp" android:layout_marginLeft="10dp" android:layout_marginTop="20dp" android:layout_marginRight="10dp" android:background="@color/white" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginLeft="10dp" android:gravity="center" android:text="用户名:" android:textColor="@color/text_9f9f9f" android:textSize="24sp" /> <TextView android:id="@+id/sys_fra_tv_username" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginLeft="10dp" android:gravity="center" android:textColor="@color/text_9f9f9f" android:textSize="24sp" /> LinearLayout> <Button android:id="@+id/btn_out" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="退出" android:textColor="@color/white">Button> LinearLayout>
二、bind方式,和上面相比,写的代码更少
1、首先打开bind方式,在build.gradle文件中andriod节点添加
dataBinding{ enabled = true }
2、添加bind类,在布局文件最高点右击添加,里面也进行了些修改,是不是有点VUE的感觉,呵呵。
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <data> <variable name="data" type="com.yysoft.syjz.vm.UserViewModel" /> data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/gray_f0f0f0" android:orientation="vertical" tools:context="com.yysoft.syjz.Fragments.SysFragment"> <LinearLayout android:layout_width="match_parent" android:layout_height="80dp" android:layout_marginLeft="10dp" android:layout_marginTop="20dp" android:layout_marginRight="10dp" android:background="@color/white" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginLeft="10dp" android:gravity="center" android:text="用户Id:" android:textColor="@color/text_9f9f9f" android:textSize="24sp" /> <TextView android:id="@+id/sys_fra_tv_userid" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginLeft="10dp" android:gravity="center" android:text="@{data.userId}" android:textColor="@color/text_9f9f9f" android:textSize="24sp" /> LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="80dp" android:layout_marginLeft="10dp" android:layout_marginTop="20dp" android:layout_marginRight="10dp" android:background="@color/white" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginLeft="10dp" android:gravity="center" android:text="用户名:" android:textColor="@color/text_9f9f9f" android:textSize="24sp" /> <TextView android:id="@+id/sys_fra_tv_username" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginLeft="10dp" android:gravity="center" android:text="@{data.userName}" android:textColor="@color/text_9f9f9f" android:textSize="24sp" /> LinearLayout> <Button android:id="@+id/btn_out" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="退出" android:textColor="@color/white">Button> LinearLayout> layout>
3、Fragment文件中添加代码
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment userViewModel = new UserViewModel(getActivity()); binding = FragmentSysBinding.inflate(inflater,container,false); binding.setData(userViewModel); binding.setLifecycleOwner(getActivity()); View view = binding.getRoot(); return view; }
4、在合适的地方添加更新方法,和上面一样,这里不说了。
总结,确实将原来页面上的代码提出来扔往viewmodel里面,也有了mvvm的感觉,像vue,其实也有点像mvc。是不是双向绑定还没继续试。等下一P吧。