在存储库中使用AsyncTask的Android房间查询空指针异常
我试图使用id查询保存在room local数据库中的一些数据。我从一个序列化对象接收到id,并将其传递给我的视图模型类,该类调用存储库以使用dao执行查询 asynctask用于使事物异步并从db返回请求的值。我已经创建了一个接口,并在异步任务中对其进行了初始化,因此我可以从db返回结果,但在NPE中失败 在activity中,我调用了repository并传递了序列化数据,如:在存储库中使用AsyncTask的Android房间查询空指针异常,android,android-asynctask,android-room,android-mvvm,Android,Android Asynctask,Android Room,Android Mvvm,我试图使用id查询保存在room local数据库中的一些数据。我从一个序列化对象接收到id,并将其传递给我的视图模型类,该类调用存储库以使用dao执行查询 asynctask用于使事物异步并从db返回请求的值。我已经创建了一个接口,并在异步任务中对其进行了初始化,因此我可以从db返回结果,但在NPE中失败 在activity中,我调用了repository并传递了序列化数据,如: public class ViewSessionActivity extends AppCompatActi
public class ViewSessionActivity extends AppCompatActivity implements View.OnClickListener{
private static final String TAG = ViewSessionActivity.class.getSimpleName();
private Toolbar toolbar;
private Sessions sessions; // serialized object from adapter
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_session);
init();
setSupportActionBar(toolbar);
}
private void init() {
// skipped fvid calls
sessions = (Sessions) getIntent().getSerializableExtra(Constants.SESSION_DETAIL_KEY);
Log.d(TAG, "Prog id:\t" + sessions.prog_sessionId);
//error occurs here which leads to async task call in repository
SessionsRepository.getRepository(getApplication()).getSessionByID(sessions.prog_sessionId);
}
在存储库中:
public class SessionsRepository {
private static final String TAG = SessionsRepository.class.getSimpleName();
private SessionsDAO dao;
private static SessionsRepository repository = null;
private LiveData<List<Sessions>> allSessions;
private MutableLiveData<Boolean> loadingState;
private Context context;
private final SportsDatabase database;
public SessionsRepository(Application application) {
database = SportsDatabase.getInstance(application);
dao = database.sessionsDAO();
allSessions = dao.getAllSessions();
loadingState = new MutableLiveData<>();
context = application.getApplicationContext();
}
public static SessionsRepository getRepository(Application context){
if (repository == null){
repository = new SessionsRepository(context);
}
return repository;
}
public void fetchSessions() {
String coachId = new PrefsUtils(context).getCoachId();
Call<SessionDetails> call = RestClient.getRestInstance().getSessionsService().fetchSessions(coachId);
call.enqueue(new Callback<SessionDetails>() {
@Override
public void onResponse(Call<SessionDetails> call, Response<SessionDetails> response) {
if (response.isSuccessful()) {
loadingState.postValue(false); // remove progress
SessionDetails details = response.body();
List<Sessions> sessions = details.getSessions();
// Log.d(TAG, "N/w sesh size:\t" + sessions.size());
saveSessions(sessions);
}
}
@Override
public void onFailure(Call<SessionDetails> call, Throwable t) {
loadingState.postValue(false);
Toast.makeText(context, "Error Fetching Sessions", Toast.LENGTH_SHORT).show();
}
});
}
private void saveSessions(List<Sessions> sessions) {
new SaveSessionsTask(dao).execute(sessions);
}
// this method which calls the async task
public void getSessionByID(String id){
new FindSessionTask(dao, context).execute(id);
}
public LiveData<List<Sessions>> getSavedSessions() {
return allSessions;
}
public class SaveSessionsTask extends AsyncTask<List<Sessions>, Void, Void> {
private SessionsDAO dao;
public SaveSessionsTask(SessionsDAO dao) {
this.dao = dao;
}
@Override
protected Void doInBackground(List<Sessions>... lists) {
dao.addSessions(lists[0]);
return null;
}
}
public class FindSessionTask extends AsyncTask<String, Void, Sessions>{
private SessionsDAO dao;
private OnSessionResultCallback callback;
public FindSessionTask(SessionsDAO dao, Context context) {
this.dao = dao;
this.callback = (OnSessionResultCallback) context;
}
@Override
protected Sessions doInBackground(String... strings) {
Sessions sessions = dao.getSessionById(strings[0]);
return sessions;
}
@Override
protected void onPostExecute(Sessions sessions) {
super.onPostExecute(sessions);
Log.d(SessionsRepository.TAG, "Session name:\t" + sessions.session_name);
}
}
// need help in returning the session found from db in onpostexecute method
}
logcat中的错误:
Caused by: java.lang.ClassCastException: sashi.in.ecosports.extras.App cannot be cast to sashi.in.ecosports.interfaces.OnSessionResultCallback
at sashi.in.ecosports.rest.db.repositories.SessionsRepository$FindSessionTask.<init>(SessionsRepository.java:110)
at sashi.in.ecosports.rest.db.repositories.SessionsRepository.getSessionByID(SessionsRepository.java:82)
at sashi.in.ecosports.ui.activities.ViewSessionActivity.init(ViewSessionActivity.java:63)
at sashi.in.ecosports.ui.activities.ViewSessionActivity.onCreate(ViewSessionActivity.java:38)
at android.app.Activity.performCreate(Activity.java:6671)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
....
原因:java.lang.ClassCastException:sashi.in.ecosports.extras.App无法强制转换为sashi.in.ecosports.interfaces.OnSessionResultCallback
位于sashi.in.ecosports.rest.db.repositories.SessionRepository$FindSessionTask。(sessionRepository.java:110)
位于sashi.in.ecosports.rest.db.repositories.sessionRepository.getSessionByID(sessionRepository.java:82)
位于sashi.in.ecosports.ui.activities.ViewSessionActivity.init(ViewSessionActivity.java:63)
在sashi.in.ecosports.ui.activities.ViewSessionActivity.onCreate(ViewSessionActivity.java:38)
位于android.app.Activity.performCreate(Activity.java:6671)
位于android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
....
我本想注销找到的会话名称,但却得到了NPE。有人能帮我执行房间异步查询吗?使用实体字段作为搜索字符串,从列表中返回整个实体。视图模型如何接收数据?是否需要我的接口?谢谢。因为您在尝试打印会话时获得了NPE。会话\u name这意味着您返回的会话对象为空,可能发生以下情况:
@update
注释,该注释通过其主键查找传递的对象并更新所有列,或者使用@query
注释更新特定列,如@query(“更新会话集会话名称=:newName WHERE prog\u sessionId=:id”)
更新会话名称列,会话id为id
。下面是一个示例代码:
@Dao
public interface SessionsDAO {
@Query("SELECT * FROM sessions") // Retrieve all columns saved in sessions table
LiveData<List<Sessions>> getAllSavedSessions();
@Query("SELECT * FROM sessions WHERE prog_sessionId = :id") // Retrieve a single session with all columns saved in sessions table
Sessions findSessionWithId(String id);
@Query("SELECT session_name FROM sessions WHERE prog_sessionId = :id") // Retrieve a single session name saved in sessions table
String getSessionNameWithId(String id);
@Update // Update all non-primary columns of a session
void updateSession(Sessions session);
@Query("UPDATE sessions SET session_name = :newName") // Update session_name column of all saved sessions
void updateAllSessionNamesTo(String newName);
@Query("UPDATE sessions SET session_name = :newName WHERE prog_sessionId = :id") // Update session_name column of a session located with its id
void updateSessionNameTo(String newName, String id);
@Query("UPDATE sessions SET session_name = :newName AND session_date = :newDate WHERE prog_sessionId = :id") // Update session_name and session_date column of a session located with its id
void updateSessionNameAndDateTo(String newName, long newDate, String id);
}
下面是一个通过检索实体并在最后返回更新的实体来更新会话名称的示例
@Dao
public abstract class SessionsDAO {
void updateSessionNameWithId(final String id, final String newName, final SessionUpdateListener onFinishListener) {
Executors.newSingleThreadExecuter().submit(new Runnable() {
@Override
public void run() {
updateSessionName(id, newName, onFinishListener);
}
});
}
@Transaction
void updateSessionName(String id, String newName, SessionUpdateListener onFinishListener) {
Sessions session = findSessionWithId(id);
session.setName(newName);
updateSession(session);
onFinishListener.onSessionUpdated(session);
}
@Query("SELECT * FROM sessions WHERE prog_sessionId = :id") // Retrieve a single session with all columns saved in sessions table
Sessions findSessionWithId(String id);
@Update // Update all non-primary columns of a session
void updateSession(Sessions session);
public interface SessionUpdateListener {
void onSessionUpdated(Sessions session);
}
}
希望您能收到备忘录。请附上您的航海日志,再次查看。你能分享一下如何使用mvvm架构在房间里执行按id查找、按id查找和更新查询吗?你说你得到了
NullPointerException
,但在你附带的日志中我看到了ClassCastException
。你把它贴好了吗?哦,很抱歉。当我试图打印session.session_名称时,NPE出现了,但它们是相关的。错误在这一行this.callback=(OnSessionResultCallback)上下文中代码><代码>上下文
是应用程序上下文,但它应该是一个回调。我已经使用stetho可视化了db,感谢链接,很高兴知道这是一个很好的选择。另外,id是正确的,因为我已经在activity的init()中注销了它,并且它打印的值与db中的值相同。您能否使用room共享findById和findById更新查询的更详细的通用答案?我来自MongoDB背景。感谢you@DarthPlagueris不客气,请看我的更新答案。是的,我理解这一部分,但问题在于它的异步部分,因为查询不能在主线程上运行。您能否帮助完成findbyid的异步任务并返回结果?感谢您dao类中的抽象前缀将方法标记为实现方法的需要,以便Room实现,您不必在任何地方实现它们,Room为您实现它们,因为它需要与数据库一起工作。正如我所说的,使用抽象类而不是接口有助于为方法提供一个主体,而不需要空间来实现它。在我们的例子中,在工作线程上运行抽象(数据库操作)方法迫使我们声明一个方法,并在其中使用Java执行器,然后运行抽象db方法。你可以声明所有的db操作方法,比如abstract Session get()
,以强制Room实现它。在仔细考虑了这个问题之后,我决定继续使用接口作为我的dao类。我几乎没有时间切换所有内容,因为结果界面仍然会抛出错误。先生,谢谢你的时间和努力。我会接受你的回答,希望你能给我更多的帮助。
@Dao
public interface SessionsDAO {
@Query("SELECT * FROM sessions") // Retrieve all columns saved in sessions table
LiveData<List<Sessions>> getAllSavedSessions();
@Query("SELECT * FROM sessions WHERE prog_sessionId = :id") // Retrieve a single session with all columns saved in sessions table
Sessions findSessionWithId(String id);
@Query("SELECT session_name FROM sessions WHERE prog_sessionId = :id") // Retrieve a single session name saved in sessions table
String getSessionNameWithId(String id);
@Update // Update all non-primary columns of a session
void updateSession(Sessions session);
@Query("UPDATE sessions SET session_name = :newName") // Update session_name column of all saved sessions
void updateAllSessionNamesTo(String newName);
@Query("UPDATE sessions SET session_name = :newName WHERE prog_sessionId = :id") // Update session_name column of a session located with its id
void updateSessionNameTo(String newName, String id);
@Query("UPDATE sessions SET session_name = :newName AND session_date = :newDate WHERE prog_sessionId = :id") // Update session_name and session_date column of a session located with its id
void updateSessionNameAndDateTo(String newName, long newDate, String id);
}
@Dao
public abstract class SessionsDAO {
void getSessionNameWithId(final String id, final NameLoadedListener onFinishListener) {
Executors.newSingleThreadExecuter().submit(new Runnable() {
@Override
public void run() {
String name = getSessionNameWithId(id);
onFinishListener.onNameLoaded(name);
}
});
}
@Query("SELECT session_name FROM sessions WHERE prog_sessionId = :id") // Retrieve a single session name saved in sessions table
abstract String getSessionNameWithId(String id);
public interface NameLoadedListener {
void onNameLoaded(String name);
}
}
@Dao
public abstract class SessionsDAO {
void updateSessionNameWithId(final String id, final String newName, final SessionUpdateListener onFinishListener) {
Executors.newSingleThreadExecuter().submit(new Runnable() {
@Override
public void run() {
updateSessionName(id, newName, onFinishListener);
}
});
}
@Transaction
void updateSessionName(String id, String newName, SessionUpdateListener onFinishListener) {
Sessions session = findSessionWithId(id);
session.setName(newName);
updateSession(session);
onFinishListener.onSessionUpdated(session);
}
@Query("SELECT * FROM sessions WHERE prog_sessionId = :id") // Retrieve a single session with all columns saved in sessions table
Sessions findSessionWithId(String id);
@Update // Update all non-primary columns of a session
void updateSession(Sessions session);
public interface SessionUpdateListener {
void onSessionUpdated(Sessions session);
}
}