当前位置: 首页 > 知识库问答 >
问题:

在存储库中使用AsyncTask查询空指针异常

颜文昌
2023-03-14

asynctask用于使事情异步化并从DB返回请求的值。我已经创建了一个接口,并在异步任务中初始化了它,这样我就可以从db返回结果,但它在NPE中失败了。

在活动中,我调用了repository并传递了序列化的数据,如下所示:

   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


}

dao类:

@Dao
public interface SessionsDAO {

    @Insert
    void addSessions(List<Sessions> sessions);

    @Query("select * from sessions")
    LiveData<List<Sessions>> getAllSessions();

    @Query("select * from sessions where prog_sessionId = :id")
    Sessions getSessionById(String id); // here

}
    public interface OnSessionResultCallback {
       void onSessionFound(Sessions sessions);
    }

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)
....

我希望注销找到的会话名称,但却得到了NPE。有人能帮我执行房间查询异步,使用一个实体字段作为搜索字符串返回整个实体从一个列表。视图模型如何接收数据,我的接口是必要的吗?多谢了。

共有1个答案

万修为
2023-03-14

由于您在尝试打印session.session_name时得到了NPE,这意味着返回的会话对象为null,这可能发生:

>

  • 查询错误(由于您的select查询是正常的,我猜您传递的id是错误的)

    当您还没有插入任何带有该id的记录时(在这种情况下,您必须调试插入过程并检查数据库以查看插入是否正确)

    要在运行时检查数据库内容,可以轻松地使用Stetho。

    此外,关于带有room的更新查询,您可以使用内置的@update批注,该批注通过其主键查找传递的对象并更新所有列,或者使用@query批注更新特定列,如@query(“update sessionset session_name=:newname WHERE prog_sessionId=:id”)(“update session_name”),该批注使用id的会话id更新session_name列。下面是示例代码:

    @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);
    }
    

    如果您需要在工作线程上运行查询,您可以使用java执行器,下面是一个检索会话名称的简单示例:

    @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);
        }
    }
    

    希望你拿到备忘录。

  •  类似资料:
    • 我对spring boot和JPA相当陌生。我正在做我的学习目的的小项目。 实体类 有线索吗?

    • 当我们尝试用Null值获取数据时 IN子句获得空指针异常。 也许是因为这个。 在数据库中,我们可以提供null in IN子句。 jooq中存在一个“无法修复”的问题https://github.com/jOOQ/jOOQ/issues/3867 有一些替代方案: 在输入前检查null(在我的情况下,这是一个非常大的select语句) 所以如果我想让这成为可能,还有其他的解决方法吗。 注:类似的情

    • 问题内容: 有可能这可能是一个双重问题。我将String变量初始化为null。我可能会或可能不会使用一个值更新它。现在我想检查此变量是否不等于null以及我尝试执行的操作是否会得到null指针异常。空指针异常,因为它代价高昂。是否有任何有效的解决方法.TIA 问题答案: 如果您使用 你 不会 得到。 我怀疑你在做什么: 这是因为null 而引发,而不是因为null。 如果仍然无法解释,请发布您用于

    • 我已经更新了我的项目中的一些依赖关系之后,我的Hibernate配置类显示Nullpointerx的。 我将SpringDataJPA存储库与hibernate一起使用,已经超过24小时了,仍然没有找到任何关于小问题的适当解决方案。 我已经尝试过的一些解决方案:- 使用@bean(name=“entityManagerFactory”)提供bean名称 我面临的问题 波姆。xml文件 配置类 db

    • 我的代码有问题。WSDL文件由来自apache cxf的wsdl2java解析。现在,我试图获得与web服务的连接,但仍然得到空指针异常。 url地址指向我下载WSDL文件的位置。为了构建jar,我使用了Maven,其依赖项如下: jaxws-api 超文本传输协议 cxf-rt前端-jaxws cxf-rt-bindings-肥皂 带有deps的jar是由maven assembly插件创建的

    • 我有一个com。谷歌。云存储Blob对象。我可以在java代码中下载和上传这个对象,但我想在启动进程之前检查一下是否存在某些东西。简而言之,这里是我的代码中给我带来问题的部分。 Eclipse似乎无法在IDE中捕获它。示例似乎也遵循此布局。有人知道发生了什么事吗? 我正在Linux环境机器上运行。(它在云功能方面也失败了)。我正在使用Java 11运行时。