接上一篇文章的概念分析的内容,这篇文章主要给出一个实际的mvvm例子来分析。
上一篇文章在这里Android架构体系–结构和组件选择
样例目的
通过mvvm模式和room(google提供的持久化库)来进行user类的显示/添加功能
结构
view:MainActivity(显示user),AddNewUserActivity(添加user)
viewmodel:UserViewModel(负责与model层通信,持有repository实例,并提供获取/插入user的操作)
model:user(实例类),userdao,appdatabase(初始化数据库实例类),userrepository(通过userdao提供数据库操作的具体实现的类)
View
MainActivity
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
public class MainActivity extends AppCompatActivity { private UserViewModel viewModel;//1.持有viewmodel实例 public static final int NEW_WORD_ACTIVITY_REQUEST_CODE = 1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(MainActivity.this, NewUserActivity.class); startActivityForResult(intent, NEW_WORD_ACTIVITY_REQUEST_CODE); } }); RecyclerView recyclerView = findViewById(R.id.recyclerview); final UserListAdapter adapter = new UserListAdapter(this); recyclerView.setAdapter(adapter); recyclerView.setLayoutManager(new LinearLayoutManager(this)); viewModel = ViewModelProviders.of(this).get(UserViewModel.class);//2.获取实例,可以根据生命周期自动管理,防止内存泄露 viewModel.getAllUsers().observe(this, new Observer<List<User>>() {//3.使用livedata的回调来更新数据 @Override public void onChanged(@Nullable List<User> users) { adapter.setUsers(users); } }); } public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == NEW_WORD_ACTIVITY_REQUEST_CODE && resultCode == RESULT_OK) { User user = new User(); user.setFirstName(data.getStringExtra(NewUserActivity.EXTRA_REPLY)); viewModel.insert(user);//4.使用viewmodel做操作 } else { Toast.makeText( getApplicationContext(), R.string.empty_not_saved, Toast.LENGTH_LONG).show(); } } } |
1.持有viewmodel实例
2.通过viewmodelproviders获取viewmodel实例,这样可以绑定activity生命周期,防止内存泄露
3.livedata可以设置observe,当数据发生改变时,会调用这个回调
4.用viewmodel进行操作
其他类,略,详见具体代码
ViewModel
UserViewModel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class UserViewModel extends AndroidViewModel{ private UserRepository mRepository;//1.reposity实例 private LiveData<List<User>> mAllUsers;//2.livedata,用来在有更改时通知ui public UserViewModel (Application application) { super(application); mRepository = new UserRepository(application); mAllUsers = mRepository.getAllUsers(); } public LiveData<List<User>> getAllUsers() { return mAllUsers; } public void insert(User word) { mRepository.insert(word); } } |
1.reposity实例
2.livedata,用来变更时通知ui
Model
通过Repository来使用database,dao,进行数据库操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
public class UserRepository { private UserDao mUserDao; private LiveData<List<User>> mAllUsers;//1.livedata,通知变更 public UserRepository(Application application) { AppDatabase db = AppDatabase.getDatabase(application);//2.获取数据库实例 mUserDao = db.userDao(); mAllUsers = mUserDao.getAll();//3.获得初始数据 } public LiveData<List<User>> getAllUsers() { return mAllUsers; } public void insert (User word) { new insertAsyncTask(mUserDao).execute(word);//插入操作 } private static class insertAsyncTask extends AsyncTask<User, Void, Void> {//4.后台操作数据库 private UserDao mAsyncTaskDao; insertAsyncTask(UserDao dao) { mAsyncTaskDao = dao; } @Override protected Void doInBackground(final User... params) { mAsyncTaskDao.insertAll(params[0]); return null; } } } |
1.livedata,用来接收数据库的返回,保持一致
2.获取数据库实例,单例模式
3.获取数据
4.利用asynctask后台操作数据库,避免卡顿
分析
1.可以看到,我们的activity层持有了viewmodel实例,用它来做逻辑操作
2.viewmodel层不持有activity的任何实例,实现了逻辑与界面的解绑,如果需要更新ui,可以用livedata或者databinding等方式来实现
3.在model层,我们也不获取viewmodel实例,可以单独测试,这一层会根据业务不同,可以是数据获取(网络请求),数据操作(数据库)等等
4.在这个例子中,我们使用了room,livedata,lifecycle,等谷歌新提供的工具库来编写,这些工具有效的增强了mvvm模式开发的便捷性。
例子改编自google官方的room例子,结构图如下
完整代码
见这里,https://github.com/u3shadow/mvvm
1 Comment