• 11
name

A PHP Error was encountered

Severity: Notice

Message: Undefined index: userid

Filename: views/question.php

Line Number: 191

Backtrace:

File: /home/prodcxja/public_html/questions/application/views/question.php
Line: 191
Function: _error_handler

File: /home/prodcxja/public_html/questions/application/controllers/Questions.php
Line: 433
Function: view

File: /home/prodcxja/public_html/questions/index.php
Line: 315
Function: require_once

name Punditsdkoslkdosdkoskdo

Room Insert List of POJO and Retrieve in Recyclerview

I am using room as data store for my app. I am trying to save a list of sessions from a successful network call in viewmodel class. I have used a repository for interacting with the dao and asynctask for making crud operations async.

Now, I'm trying to display the "saved data" in a recyclerview but it shows nothing. On inspection of my database table, I find that nothing was saved. Here's my model class:

@Entity(tableName = "sessions")
public class Sessions{

    //    @PrimaryKey(autoGenerate = true)
    //    public int id;

    @SerializedName("prg_session_image")
    public String sessionImage;

    @SerializedName("prg_session_name")
    public String session_name;

    @SerializedName("prg_session_id") // used session id as PK 
    @PrimaryKey
    @NonNull
    public String prog_sessionId;

    @SerializedName("prg_session_description")
    public String session_desc;

    @SerializedName("reference_id")
    public String reference_id;

    @SerializedName("prg_name")
    public String program_name;

    @SerializedName("batch_name")
    public String batch_name;

    @SerializedName("player_count")
    public String participants_count;

    @SerializedName("prg_session_focus_points")
    public String session_focus_points;

    @SerializedName("prg_session_equipment")
    public String equipments_reqd;

    @SerializedName("session_complete")
    public String is_complete;

    public Sessions() {
    }

     //    public int getId() {
     //        return id;
    //    }

    public String getSessionImage() {
        return sessionImage;
    }

    public void setSessionImage(String sessionImage) {
        this.sessionImage = sessionImage;
    }

    public String getSession_name() {
        return session_name;
    }

    public void setSession_name(String session_name) {
        this.session_name = session_name;
    }

    public String getProg_sessionId() {
        return prog_sessionId;
    }

    public void setProg_sessionId(String prog_sessionId) {
        this.prog_sessionId = prog_sessionId;
    }

    public String getSession_desc() {
        return session_desc;
    }

    public void setSession_desc(String session_desc) {
        this.session_desc = session_desc;
    }

    public String getReference_id() {
        return reference_id;
    }

    public void setReference_id(String reference_id) {
        this.reference_id = reference_id;
    }

    public String getProgram_name() {
        return program_name;
    }

    public void setProgram_name(String program_name) {
        this.program_name = program_name;
    }

    public String getBatch_name() {
        return batch_name;
    }

    public void setBatch_name(String batch_name) {
        this.batch_name = batch_name;
    }

    public String getParticipants_count() {
        return participants_count;
    }

    public void setParticipants_count(String participants_count) {
        this.participants_count = participants_count;
    }

    public String getSession_focus_points() {
        return session_focus_points;
    }

    public void setSession_focus_points(String session_focus_points) {
        this.session_focus_points = session_focus_points;
    }

    public String getEquipments_reqd() {
        return equipments_reqd;
    }

    public void setEquipments_reqd(String equipments_reqd) {
        this.equipments_reqd = equipments_reqd;
    }

    public String getIs_complete() {
        return is_complete;
    }

    public void setIs_complete(String is_complete) {
        this.is_complete = is_complete;
    }
    }

And Dao class:

    @Dao
    public interface SessionsDAO {

     //    @Insert
    //    LiveData<List<Sessions>> saveSessions(List<Sessions> sessions);

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

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

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

    }

In repository, I have asynctasks for various operations with the Dao:

    public class SessionsRepository {

    public SessionsDAO dao;
    private MutableLiveData<List<Sessions>> querySingleSession;
    private LiveData<List<Sessions>> allSessions;

    public SessionsRepository(Application application){
        SportsDatabase database = SportsDatabase.getInstance(application);
        dao = database.sessionsDAO();
        querySingleSession = new MutableLiveData<>();
        allSessions = dao.getAllSessions();
    }

    public void saveSessions(List<Sessions> sessions){
        new SaveSessionsTask(dao).execute(sessions);
    }

    public LiveData<List<Sessions>> getAllSessions() {
        return allSessions;
    }

    public void getSessionById(List<Sessions> sessions){
        querySingleSession.setValue(sessions);
    }

    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 void getSessions(){
    //        new GetSessionsTask(dao).execute();
    //    }
    //    public class GetSessionsTask extends AsyncTask<Void, >

    }

I am trying to at the moment save all the results from network call and display them from the database. Here's my operation in viewmodel class:

    public class HomeSessionsViewModel extends AndroidViewModel {

    private static final String TAG = HomeSessionsViewModel.class.getSimpleName();

    private MutableLiveData<SessionDetails> liveDetails;
    private SessionsRepository repository;

    public HomeSessionsViewModel(@NonNull Application application) {
        super(application);
        repository = new SessionsRepository(application);
    }

     //    public HomeSessionsViewModel (Application application){
     //        repository = new SessionsRepository(application);
     //    }

    public MutableLiveData<SessionDetails> getSessions(){
        if (liveDetails == null){
            liveDetails = new MutableLiveData<>();
            fetchSessions();
        }
        return liveDetails;
    }

    private void fetchSessions(){
        String coachId = "4086";

        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()){
                    SessionDetails details = response.body();
                    List<Sessions> sessions = details.getSessions();
                    Log.d(TAG, "N/w sesh size:\t" + sessions.size());
                    liveDetails.setValue(details); // now just displaying from network
                    saveSessions(sessions);
                }
            }

            @Override
            public void onFailure(Call<SessionDetails> call, Throwable t) {

            }
        });

    }

    private void saveSessions(List<Sessions> sessions) {
        repository.saveSessions(sessions);
    }

    public LiveData<List<Sessions>> fetchSessionsDB(){
        return repository.getAllSessions();
    }

    }

and in ui controller (fragment), I have called the viewmodel's fetchSessionsDB() method but no data is shown. The network request works well as I was displaying from there before adding room. What could be wrong here? Thank you.

API Response:

{
             "session_details": [
                {
                    "prg_session_name": "Session-16",
                    "prg_session_id": "987",
                    "prg_session_equipment": null,
                    "prg_session_description": "",
                    "prg_session_focus_points": "",
                    "prg_session_image": "http://devsports.copycon.in/includes/uploads/Jellyfish5.jpg",
                    "session_complete": "0",
                    "prg_name": "cricket coaching",
                    "reference_id": "293",
                    "batch_id": "57",
                    "batch_name": "Batch 3",
                    "player_count": "10"
                }, .... ]}

and SessionDetails POJO:

public class SessionDetails {

@SerializedName("session_details")
@Expose
private List<Sessions> sessions;

@SerializedName("status")
private String status;

@SerializedName("message")
private String msg;

public List<Sessions> getSessions() {
    return sessions;
}
}

fragment class where db data should be displayed:

private void populateSessions() {
    sessionsRV = fragmentBinding.sessionsRV;
    sessionsRV.setHasFixedSize(false);
    LinearLayoutManager hlm = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
    sessionsRV.setLayoutManager(hlm);

    sessionsViewModel = ViewModelProviders.of(this).get(HomeSessionsViewModel.class);
   //        sessionsViewModel.fetchSessions(""); // TODO: 3/16/2019 Use coach id from db

    // calling db from viewmodel
    sessionsViewModel.fetchSessionsDB().observe(this, new Observer<List<Sessions>>() {
        @Override
        public void onChanged(@Nullable List<Sessions> sessions) {
            sessionsAdapter = new SessionsAdapter(getActivity(), sessions);
            sessionsRV.setAdapter(sessionsAdapter);
            Log.d(TAG, "Sessions Count:\t" + sessionsAdapter.getItemCount()); // logs 0
        }
    });

    // previously from network directly displayed
    //        sessionsViewModel.getSessions().observe(this, new Observer<SessionDetails>() {
    //            @Override
    //            public void onChanged(@Nullable SessionDetails details) {
    //                List<Sessions> list = details.getSessions();
    //                sessionsAdapter = new SessionsAdapter(getActivity(), list);
   //                sessionsRV.setAdapter(sessionsAdapter);
  //                Log.d(TAG, "Sessions Count:\t" + sessionsAdapter.getItemCount());
 //            }
 //        });

}

Sports Database class:

@Database(entities = {CoachDB.class, Sessions.class}, version = 1, exportSchema = false)
public abstract class SportsDatabase extends RoomDatabase {

private static SportsDatabase instance;
public abstract CoachDAO coachDAO();
public abstract SessionsDAO sessionsDAO();

public static synchronized SportsDatabase getInstance(Context context) {
    if (instance == null){
        instance = Room.databaseBuilder(context.getApplicationContext(), SportsDatabase.class, "sports_db")
                .fallbackToDestructiveMigration()
                .build();
    }
    return instance;
}

}
    • Yes, I see you've got a ton of attributes and values to handle but, you can do them, I believe. If you can log them, then turn them into a text file and then copy it as strings to initialize dummy value for the test. You must test your Room else you'll not be able to pinpoint which part the problem is in, right? Another way can be to use only two-three entries/rows and if need be a few attributes only, just for testing. I'd highly recommend you to build tests for Room anyhow as it has several advantages for the future maintenance and changes of your project.
      • 2
    • Where is your SportsDatabase class which should extend RoomDatabase? Share that class, it's the main class that builds a database with the entities. And make sure it has the database annotation like; @Database(entities = {Sessions.class}, version = 1)
      • 2
    • I'd suggest you log the network session instead of directly trying to save them to Room, just to make sure your process of getting sessions is correct before any database work. Second, test your Room database in isolation, just put some dummy sessions values preferably via a test and perform all the sessions repository actions. This way you'll make sure your Room is set up correctly. Testing Room: developer.android.com/training/data-storage/room/testing-db
      • 2
    • I have already displayed from network now I want to save and display from db. You're right on the testing part but there are too many fields to populate. Have another look at the revised question. Thanks

I have solved this issue by modifying my @insert method in dao like

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

}

and run my async task with a list of sessions as input and it worked successfully.

private void saveSessions(List<Sessions> sessions) {
    new SaveSessionsTask(dao).execute(sessions);
}

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;
    }
}
  • 1
Reply Report