In the main activity, I have LiveData which contains members and a click listener. If I click on a member, then his ID is passed with intent.putExtra. That ID is later passed on to the method open in this activity. With this activity, I want to see the details of a member. In my MemberInfo activity, I marked a line where my problem lies. It shows me this error: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
My DAO consists this code:
@Query("SELECT * FROM member_table WHERE MemberID=:id")
Member getMemberInfo(long id);
This is my main activity:
public class MemberMainActivity extends AppCompatActivity implements MemberListAdapter.MemberClickListener{
private MemberViewModel mMemberViewModel;
private List<Member> mMember;
void setMember(List<Member> members) {
mMember = members;
}
public static final int NEW_MEMBER_ACTIVITY_REQUEST_CODE = 1;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_member);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MemberMainActivity.this, NewMemberActivity.class);
startActivityForResult(intent, NEW_MEMBER_ACTIVITY_REQUEST_CODE);
}
});
RecyclerView recyclerView = findViewById(R.id.recyclerviewcard_member);
final MemberListAdapter adapter = new MemberListAdapter(this);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
mMemberViewModel = ViewModelProviders.of(this).get(MemberViewModel.class);
mMemberViewModel.getAllMember().observe(this, new Observer<List<Member>>() {
@Override
public void onChanged(@Nullable final List<Member> members) {
mMember = members;
// Update the cached copy of the words in the adapter.
adapter.setMember(members);
}
});
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == NEW_MEMBER_ACTIVITY_REQUEST_CODE && resultCode == RESULT_OK) {
Member member = new Member(data.getStringExtra(NewMemberActivity.EXTRA_REPLY), data.getStringExtra(NewMemberActivity.EXTRA_REPLY2));
mMemberViewModel.insert(member);
} else {
Toast.makeText(
getApplicationContext(),
R.string.empty_not_saved,
Toast.LENGTH_LONG).show();
}
}
public void onMemberClick(int position) {
Member member = mMember.get(position);
Intent intent = new Intent(getApplicationContext(),MemberInfo.class);
intent.putExtra("MemberID", member.getId());
MemberInfo.open(this, member.getId());
}
}
This is my activity:
public class MemberInfo extends AppCompatActivity {
public static void open(Activity activity, long memberid) {
Intent intent = new Intent(activity, MemberInfo.class);
intent.putExtra("MemberID", memberid);
activity.startActivity(intent);
}
private List<Member> mMember;
private MemberViewModel mMemberViewModel;
void setMember(List<Member> members){
mMember = members;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_memberinfo);
Log.i("okay", "memberinfo");
Intent intent = getIntent();
if (intent != null && intent.hasExtra("MemberID")) {
long memberid = intent.getLongExtra("MemberID", -1);
// TODO: get customer details based on customer id
TextView firstname = findViewById(R.id.layout_memberfirstname);
TextView surname = findViewById(R.id.layout_membersurname);
TextView balance = findViewById(R.id.layout_memberbalance);
-------------Member member = MemberRoomDatabase.getDatabase().memberDao().getMemberInfo(memberid);-------------
firstname.setText(member.getFirstname());
surname.setText(member.getSurname());
}
else {
Toast.makeText(
getApplicationContext(),
R.string.empty_not_saved,
Toast.LENGTH_LONG).show();
}
}
}
I thought that maybe it is because I'm missing a AsyncTask method. I tried this, but this also didn't work:
private static class insertMemberInfoAsyncTask extends AsyncTask<Member, Void, Void> {
private MemberDao mAsyncTaskDao;
insertMemberInfoAsyncTask(MemberDao dao) {
mAsyncTaskDao = dao;
}
@Override
protected Void doInBackground(Member... params) {
Member member = params[0];
mAsyncTaskDao.getMemberInfo(member.getId());
return null;
}
}
public Member getMemberInfo(long id) {
mAllMember = mMemberDao.getAllMember();
Member member = mMemberDao.getMemberInfo(id);
new insertMemberInfoAsyncTask(mMemberDao).execute(member);
return member;
}
I think I use the method wrong. Can anybody help me?
One option is to update your query to this:
@Query("SELECT * FROM member_table WHERE MemberID=:id")
LiveData<Member> getMemberInfo(long id);
(or similar, using Flowable
). This avoids the need to manually create your own AsyncTask
.
Returning the LiveData
wrapper around the Member
type automatically signals to Room that the query can/should be performed asynchronously. Per https://developer.android.com/training/data-storage/room/accessing-data (my emphasis):
Note: Room doesn't support database access on the main thread unless you've called
allowMainThreadQueries()
on the builder because it might lock the UI for a long period of time. Asynchronous queries—queries that return instances of LiveData or Flowable—are exempt from this rule because they asynchronously run the query on a background thread when needed.
You can use Future and Callable. So you would not be required to write a long asynctask and can perform your queries without adding allowMainThreadQueries() or using LiveData.
My dao query:-
@Query("SELECT * from user_data_table where SNO = 1")
UserData getDefaultData();
My repository method:-
public UserData getDefaultData() throws ExecutionException, InterruptedException {
Callable<UserData> callable = new Callable<UserData>() {
@Override
public UserData call() throws Exception {
return userDao.getDefaultData();
}
};
Future<UserData> future = Executors.newSingleThreadExecutor().submit(callable);
return future.get();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With