2

All I have to do is get the return value from the insert as a long. I got that but it isn't working, I am getting back 0 from the returned value. I am using a DAO, Repository and ViewModel as stated in the Google CodeLabs. I have followed this post Rowid after Insert in Room.

Player Class

@Entity(tableName = "player_table")
public class Player {
    @PrimaryKey(autoGenerate = true)
    private long id;
    @NonNull
    @ColumnInfo(name = "username")
    private String username;
}

DAO

@Insert
long insert(Player player);

Repository

public long insert(Player player) {
    new insertAsyncTask(mPlayerDao).execute(player);
    rowId = player.getId();
return rowId;
}

ViewModel

public long insert(Player player){
    rowId = mRepository.insert(player);
    return rowId;
}

Activity

String playerString = editTextUsername.getText().toString();
Player player = new Player(playerString);
long rowId = mDreamViewModel.insert(player);
Zain
  • 37,492
  • 7
  • 60
  • 84
  • Can you add the Player class? – xcesco Sep 24 '18 at 19:54
  • @xcesco Done...^^^ – William Rongholt Sep 24 '18 at 21:43
  • I am wondering if it is in the returns in the Repository/ViewModel?? – William Rongholt Sep 24 '18 at 21:55
  • This is all the code? In ViewModel#insert .. the body is { long rowId=mRepo...insert(player); return rowId; } or rowId is defined in another place? – xcesco Sep 25 '18 at 22:36
  • @xcesco yes it is just set to at the top of the viewModel long rowId – William Rongholt Sep 26 '18 at 18:13
  • In Repository not sure what to do in that but this is the updated and Ill change on original post.... public long insert(Player player) { new insertAsyncTask(mPlayerDao).execute(player); rowId = player.getId(); return rowId; } – William Rongholt Sep 26 '18 at 19:36
  • ViewModel... public long insert(Player player){ rowId = mRepository.insert(player); return rowId; } – William Rongholt Sep 26 '18 at 19:39
  • You don't mention what the problem is. What "isn't working". [Edit] the question and make sure you provide any message, details, or errors in the text of the question. Also, put relevant details from those links in the body of the text, as well. External links will be dead in an internet moment. –  Sep 26 '18 at 19:42
  • @jdv I am getting 0 as the return value – William Rongholt Sep 26 '18 at 22:46
  • Sounds like you need to focus on debugging your own code. https://ericlippert.com/2014/03/05/how-to-debug-small-programs/ –  Sep 27 '18 at 14:05
  • @jdv I could see why you would think that but I wouldn't know if it was returning a zero if I haven't tried debugging my code. I have entered logs in many places trying to figure this out. I don't ask for help just because I am lazy, I am older than that generation. – William Rongholt Sep 27 '18 at 17:59
  • @WilliamRongholt it's probably not a generational thing where you forget to say what you tried... Show your research. Tell us what you tried. –  Sep 27 '18 at 18:48
  • So I have put in multiple logs and they proved useless. I started putting in break points and checking the variable of id of player or also the one I made rowId and still all of the come back 0 in many places. – William Rongholt Oct 08 '18 at 02:40

2 Answers2

2

The problem is that you return player.getId() before the AsyncTask finishes its background work of insertion; you must wait until it delivers you the correct result of insertion, and here is a suggested solution using the thread-safe CountDownLatch which pauses the the execution of the subsequent code using .await() method until count of the CountDownLatch reaches 0; where it decrements by 1 each time .countDown() is invoked.

public class Repository {

    private long rowId = -1;
    private CountDownLatch mLatch;

    public long insert(Player player) {
        mLatch = new CountDownLatch(1);
        new insertAsyncTask(mPlayerDao).execute(player);
        try {
            mLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Log.i("LOG_TAG", String.valueOf(rowId));

        return rowId;
    }

    class insertAsyncTask extends AsyncTask<Player, Void, Void> {

        @Override
        protected Void doInBackground(Player... players) {
            rowId = mDatabase.getContactDAO().addContact(players[0]);
            mLatch.countDown();
            return null;
        }
    }

}
Zain
  • 37,492
  • 7
  • 60
  • 84
0

The insert method in your Repository class can be changed to this:

public long insert(Player player) {
    return new insertAsyncTask(mPlayerDao).execute(player).get();
}

I found this by searching GitHub for AsyncTasks with "Void, Long" as the last two types, along with some other Room-specific terms.

When debugging my own application I saw that execution of the return statement in the insert method was occurring before the doInBackground method was executed, which seemed obvious after I saw it happen.

Stuart Gilbert
  • 176
  • 1
  • 4