I had to create an account to ask this question because I couldn't find the right way to do this. The only thing that comes close is this question here, but it doesn't go all the way and I'm still stuck. Here we go...
I'm trying to build an app following as much of the Architecture Components principles. I'm currently trying to add a row in one of my database table, and get the ID of this row in return, to then insert a row in another table, with a reference to the first one.
I've created my database object:
@Entity(indices = {@Index("id")})
public class Search {
@PrimaryKey(autoGenerate = true) private int id;
...
And the corresponding DAO:
@Dao
public interface SearchDao {
@Insert
long insert(Search search);
...
As you can see, my DAO returns a long with the created ID. This is the behavior which was pointed out in the question I linked before, and documented here.
Since I'm following Android Architecture Components principles, I'm using a Repository class to do all my database related work. In this Repository, I've created a public method to insert a new object, which is creating and executing an AsyncTask to do the work:
public class Repository {
public void insertSearch(Search search) {
new insertSearchAsyncTask(this.mSearchDao).execute(search);
}
...
private static class insertSearchAsyncTask extends AsyncTask<Search, Void, Long> {
private SearchDao mAsyncTaskDao;
insertSearchAsyncTask(SearchDao dao) {
this.mAsyncTaskDao = dao;
}
@Override
protected Long doInBackground(final Search... params) {
long id = this.mAsyncTaskDao.insert(params[0]);
return id;
}
}
I know I can use the onPostExecute(long id) method to do stuff with the result of the doInBackground method, but this onPostExecute method cannot return anything to the insertSearch method, where I created the AsyncTask and executed it.
I know need to change the return type of my insertSearch method to long. However if I want to have something to return, I need to get the result of the execution of the AsyncTask. How can I do that?
I've tried this (according to the validated answer):
public class Repository {
private long result_id = 0;
public long insertSearch(Search search) {
new insertSearchAsyncTask(this.mSearchDao).execute(search);
return result_id;
}
private class insertSearchAsyncTask extends AsyncTask<Search, Void, Long> {
private SearchDao mAsyncTaskDao;
insertSearchAsyncTask(SearchDao dao) {
this.mAsyncTaskDao = dao;
}
@Override
protected Long doInBackground(final Search... params) {
long id = this.mAsyncTaskDao.insert(params[0]);
return id;
}
@Override
protected void onPostExecute(Long search_id) {
result_id = search_id;
}
}
}
But this feels very very wrong. I had to make the insertSearchAsyncTask class not-static, and I have to store the result of the insert in an attribute of my Repository. I'm hoping there is a better/correct way of doing this.
I've also looked at other suggested answers on the link above, especially one about Delegates, but this doesn't suit my need as I need the method insertSearch to return the result, not another one called by the AsyncTask when it finishes.
I hope I've explained my problem clearly enough. Any idea anyone?
Thanks a lot!!