AndroidViewModel的onChanged()跨Activity使用时无法生效
开发场景说明
正在开发一款聊天应用,包含两个核心Activity:
- 联系人Activity:负责展示联系人列表
- 消息Activity:负责展示单条会话的聊天内容
在联系人Activity中,使用如下代码初始化ChatViewModel,通过观察对应LiveData填充RecyclerView,功能运行完全正常:
contactsViewModel = new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory .getInstance(this.getApplication())).get(ChatViewModel.class); contactsViewModel.getAllUsers().observe(this, new Observer<List<UserContacts>>() { @Override public void onChanged(List<UserContacts> userContacts) { contactAdapter.submitList(userContacts); if(!userContacts.isEmpty()) { userList = userContacts; } } });
异常表现
点击某条联系人进入消息Activity后,需要获取该联系人的基础信息,因此在消息Activity中复用了相同的ViewModel初始化与观察逻辑,代码如下:
chatViewModel = new ViewModelProvider(this,ViewModelProvider.AndroidViewModelFactory.getInstance(this.getApplication())).get(ChatViewModel.class); chatViewModel.getAllUsers().observe(this, new Observer<List<UserContacts>>() { @Override public void onChanged(List<UserContacts> userContacts) { Toast.makeText(ChatActivity.this, "Inside", Toast.LENGTH_SHORT).show(); for(int i = 1; i <= userContacts.size();i++) { UserContacts user = userContacts.get(i); if(user.getId() == id) { reciever = user.getFriend(); profile = user.getPicture(); firstName = user.getFirstName(); lastName = user.getLastName(); friendPublicKeyString = user.getFriendPublicKey(); } } } });
实际运行时,该观察逻辑的onChanged()方法没有按预期触发:经调试确认,联系人Activity的对应回调可正常执行,消息Activity的执行链路完全没有进入onChanged(),所有关联的联系人信息变量最终被赋值为null。
- 调试参考1:联系人Activity的回调执行状态
- 调试参考2:消息Activity的回调未触发状态
现有各层代码实现
ChatViewModel构造函数:关联Repository并初始化所有联系人数据
public ChatViewModel(@NonNull Application application) { super(application); chatRepository = new ChatRepository(application); allContacts = chatRepository.getAllContacts(); oneChat = chatRepository.getOneChat(); allChatsJustForId = chatRepository.getAllChatsJustForId(); }
ChatViewModel对外暴露联系人LiveData的方法
public LiveData<List<UserContacts>> getAllUsers() { return allContacts; }
ChatRepository构造函数:从Room数据库初始化所有联系人数据
public ChatRepository(Application application) { ChatDatabase db = ChatDatabase.getInstance(application); chatDao = db.chatDao(); userContactsDao = db.userContactsDao(); allContacts = userContactsDao.getAllContacts(); senderHelperDao = db.senderHelperDao(); oneChat = senderHelperDao.getOneChat(); allChatsJustForId = chatDao.getAllChatJustSoICanSeeMaxPrimaryKey(); }
ChatRepository对外暴露联系人LiveData的方法
public LiveData<List<UserContacts>> getAllContacts() { return allContacts; }
UserContactsDao中查询联系人的DAO定义
@Query("SELECT * FROM UserContacts ORDER BY priority DESC") LiveData<List<UserContacts>> getAllContacts();
问题排查方向
- 代码逻辑bug校验:消息Activity的观察回调内循环从
i=1开始取值、循环终止条件为i <= userContacts.size(),存在数组越界风险(List索引从0开始,当i等于集合大小时直接取值会抛出IndexOutOfBoundsException),需要先修正循环范围为i=0; i < userContacts.size()。 - ViewModel作用域校验:当前代码中
ViewModelProvider的第一个参数传入的是当前Activity实例,两个Activity会分别从各自的ViewModelStore中获取独立的ChatViewModel实例,并非全局共享。虽然Room生成的LiveData支持多观察者同时观察,但需要确认观察注册时Activity是否处于活跃状态、是否有前置代码抛出异常导致observe()调用未执行到。 - 前置变量校验:确认消息Activity中用于匹配联系人的
id变量是否正确从Intent中获取,避免空值、类型不匹配导致的前置逻辑崩溃,阻断观察逻辑的注册流程。 - 数据源单例校验:确认Room数据库实例、DAO实例、Repository层持有的LiveData引用均为单例,避免因为多实例初始化导致的LiveData绑定异常,无法向观察者推送数据。
内容的提问来源于stack exchange,提问作者M.Ahmed
相关产品推荐
相关产品推荐

