Room数据库单行列数据获取空指针问题求助
问题分析与解决
核心问题1:ViewModel未初始化
你在POIActivity中仅声明了RouteViewModel routeViewModel,但未对其进行实例化,直接调用routeViewModel.getPoiStrings()必然触发空对象引用错误。
核心问题2:Room主线程操作违规
Room默认禁止在主线程执行同步数据库查询(避免阻塞UI),当前getPoiLinks()是同步方法,直接调用会抛出IllegalStateException,这也是潜在的崩溃点。
修复步骤
1. 正确初始化ViewModel
在POIActivity的onCreate方法中,使用ViewModelProvider获取ViewModel实例:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_poiactivity); // 初始化ViewModel routeViewModel = new ViewModelProvider(this).get(RouteViewModel.class); clickedPosition = getIntent().getIntExtra("clickedPosition", 0); iv_imageView1 = findViewById(R.id.tv_imageView1); iv_imageView2 = findViewById(R.id.iv_imageView2); // 后续通过观察LiveData或协程获取数据 }
2. 修改DAO为异步兼容方式
将DAO的查询方法改为返回LiveData<String>,让Room自动在后台线程执行查询:
@Dao public interface RouteDao { // ... 其他方法 @Query("SELECT poiLinks FROM route_table WHERE id = :position") LiveData<String> getPoiLinks(int position); }
3. 调整Repository和ViewModel
更新Repository返回LiveData,ViewModel直接暴露该LiveData供Activity观察:
// Repository类 public class RouteRepository { // ... 其他代码 public LiveData<String> getPoiString(int position){ return mRouteDao.getPoiLinks(position); } } // ViewModel类 public class RouteViewModel extends AndroidViewModel { // ... 其他代码 public LiveData<String> getPoiStrings(int position){ return mRepository.getPoiString(position); } }
4. 在Activity中观察数据
通过observe方法监听LiveData的变化,在数据返回后更新UI:
@Override protected void onCreate(Bundle savedInstanceState) { // ... 已有的初始化代码 routeViewModel.getPoiStrings(clickedPosition).observe(this, poiLinks -> { if(poiLinks != null){ poiLinkString = poiLinks; // 在这里处理获取到的poiLinks,比如加载图片等操作 } }); }
可选方案:使用协程处理异步查询
如果你更喜欢用协程而非LiveData,也可以这样修改:
- DAO方法保持同步:
@Dao public interface RouteDao { // ... 其他方法 @Query("SELECT poiLinks FROM route_table WHERE id = :position") String getPoiLinks(int position); }
- Repository中用协程封装:
public class RouteRepository { // ... 其他代码 public suspend String getPoiString(int position){ return mRouteDao.getPoiLinks(position); } }
- ViewModel中用
viewModelScope执行协程:
public class RouteViewModel extends AndroidViewModel { // ... 其他代码 public void getPoiStrings(int position, OnPoiLoadedListener listener){ viewModelScope.launch { String poiLinks = mRepository.getPoiString(position); listener.onLoaded(poiLinks); } } // 定义回调接口 public interface OnPoiLoadedListener { void onLoaded(String poiLinks); } }
- Activity中调用并处理结果:
@Override protected void onCreate(Bundle savedInstanceState) { // ... 已有的初始化代码 routeViewModel.getPoiStrings(clickedPosition, new RouteViewModel.OnPoiLoadedListener() { @Override public void onLoaded(String poiLinks) { if(poiLinks != null){ poiLinkString = poiLinks; // 处理数据 } } }); }
内容的提问来源于stack exchange,提问作者Smash
相关产品推荐
相关产品推荐

