Unable to delete table from room database - java

I have implemented Room Persistence Library in my App. Using this i'm
1.Adding data to a table
2.Displaying it
3.Deleting table
Im Doing these three steps In a loop.
But Problem here is Table content gets deleted only after restart the app. Means table data wont get deleted until i restart the app.
My code is here
Adding,Reading,Displaying Database table
public void DatabaseTask{
for(getting data from web server){
//Adding them to database
AddToDatabase addToDatabase=new AddToDatabase(file.getId(),file.getName(),"punith#gmail.com");
addToDatabase.execute();
}
//Reading Table from Database
ReadFromDatabase readFromDatabase=new ReadFromDatabase();
readFromDatabase.execute();
//Deleting table from database
DeleteFromDatabase deleteFromDatabase=new DeleteFromDatabase();
deleteFromDatabase.execute();
}
This DatabaseTask class will be executed every 15 minutes
Asynch Task Class for Adding,Reading,Deleting
private class AddToDatabase extends AsyncTask<String,String,String>{
String id;
String name,email;
public AddToDatabase(String id,String name, String email){
this.id=id;
this.name=name;
this.email=email;
}
#Override
protected String doInBackground(String... strings) {
User user=new User();
user.setId(id);
user.setName(name);
user.setEmail(email);
MainActivity.myAppDatabase.myDao().addUser(user);
return null;
}
#Override
protected void onPostExecute(String s) {
Log.d("mPavan001", "add done");
super.onPostExecute(s);
}
}
private class ReadFromDatabase extends AsyncTask<String,String,String>{
#Override
protected String doInBackground(String... strings) {
List<User> users=MainActivity.myAppDatabase.myDao().getUsers();
for(User usr: users){
String id=usr.getId();
String name=usr.getName();
String email=usr.getEmail();
info=info+"\n\n"+"id :"+id+"\n Name :"+name+"\n Email :"+email;
}
return null;
}
#Override
protected void onPostExecute(String s) {
Log.d("mPavan001", "onPostExecute: "+info);
super.onPostExecute(s);
}
}
private class DeleteFromDatabase extends AsyncTask<String,String,String>{
#Override
protected String doInBackground(String... strings) {
MainActivity.myAppDatabase.myDao().deleteAll();
return null;
}
#Override
protected void onPostExecute(String s) {
Log.d("mPavan001", "delete done");
super.onPostExecute(s);
}
}
data access object
#Dao
public interface MyDao {
#Insert
public void addUser(User user);
#Query("select * from users")
public List<User> getUsers();
#Query("DELETE FROM users")
public void deleteAll();
}
How can i resolve this issue?
Please ask if you need more details.

It looks like you are just deleting data, without listening for its changes.
Consider getting data from database using LiveData, and observing LiveData in your Fragment or Activity. That way your view will be always aware of data changes.
One more thing is that you probably are checking for data changes manually after deleting it. If so: please post your code for that block.

I did a silly mistake , I was using info string to display the database table value. but I was not setting it to null on every loop iteration. So it used to store data from previous loop iteration as well , Even though the database table was getting deleted!

Related

Sequential AsyncTasks where each following use result from previous

I thought a bit about this and I was wondering which could be the best pattern to accomplish my request.
Real case:
I have many web calls which must be sequential and where every call must use the result of the previous. This is the concept of what I mean:
Suppose to have this db structure:
User [id, server-side created info, infos]
House [id, server-side created info, user ref, infos]
Room [id, server-side created info, house ref, infos]
Suppose that with my app (offline) an user can create his user entity, N house entities and N room entities for each house.
Then, once done, the user is syncing data with server.
This is what should be done:
For each user, send user to webapi and read the server-side info.
For each house of the sent user, read the server-side info, send the house to webapi and read the server-side info.
For each room of the sent house, read the server-side info, send the room to webapi and read the server-side info.
This might be done this way:
Create an AtomicInteger that is the count of all sync to be done.
Init this value with the sum of users, houses, rooms.
void syncDone() {
if(totalSyncCounter.decrementAndGet() == 0){
//sync finished, prompt user
}
}
Create AsyncTasks
class SendUserToDbAsyncTask extends AsyncTask<User, Void, Integer> {
UserSavedCallback _callback;
public SendUserToDbAsyncTask(UserSavedCallback _callback) {
this._callback = _callback;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Integer doInBackground(User... users) {
//save user and return the server-side value
return serverSideInfo;
}
#Override
protected void onPostExecute(Integer res) {
super.onPostExecute(res);
_callback.onResult(res);
}
}
class SendHouseToDbAsyncTask extends AsyncTask<House, Void, Integer> {
HouseSavedCallback _callback;
public SendHouseToDbAsyncTask(HouseSavedCallback _callback) {
this._callback = _callback;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Integer doInBackground(House... houses) {
//save user and return the server-side value
return serverSideInfo;
}
#Override
protected void onPostExecute(Integer res) {
super.onPostExecute(res);
_callback.onResult(res);
}
}
class SendRoomToDbAsyncTask extends AsyncTask<User, Void, Integer> {
RoomSavedCallback _callback;
public SendRoomToDbAsyncTask(RoomSavedCallback _callback) {
this._callback = _callback;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Integer doInBackground(Room... rooms) {
//save user and return the server-side value
return serverSideInfo;
}
#Override
protected void onPostExecute(Integer res) {
super.onPostExecute(res);
_callback.onResult(res);
}
}
Logic:
void DoStuffs() {
mySyncCounter = [users + houses + rooms];
for (User user : users) {
new SendUserToDbAsyncTask(new UserSavedCallback() {
void onResult(){
syncDone();
for (House house : user.houses) {
new SendHouseToDbAsyncTask(new HouseSavedCallback() {
void onResult(){
syncDone();
for (Room room : house.rooms) {
new SendRoomToDbAsyncTask(new RoomSavedCallback() {
void onResult(){
syncDone();
}).execute(room);
}
}).execute(house);
}
}).execute(user);
}
}
Obiouvsly it is just an example hand-wrote here on SO. I just want to make you get the point. I know I can make a single callback for all, init it outside the method, just create a single asynctask for everything, etc... but I'm not looking for any suggestion about optimizing this specific code, I just want to know how to perform multiple sequential async operations where every following operation use the return of the previous.
What is the best way for performing this kind of operations?
Is there a "cleaner" way of doing it?
Thanks
If I understand correctly.
You could use ExecutorService to make calls to the sync server, and Semaphore to stop the thread as you like.
Only you will have to use AsyncTask anyway, because the calls would only fail with ExecutorService

How do I update a field in a room database using a repository & viewmodel

I created a room database following this guide from code labs It makes use of a repository to:
A Repository manages query threads and allows you to use multiple backends. In the most common example, the Repository implements the logic for deciding whether to fetch data from a network or use results cached in a local database.
I followed the guide and i'm now able to create the entity's & retrieve the data. I even went further and created another whole entity outside the scope of the guide.
However I can't find many resources that use this MVVM(?) style so am struggling as to really under stand the repository. For now I want to update a field. Just one, as if I am able to manage that the rest should be similar.
I want to update a field called dartshit and I have the dao method created for this:
#Query("UPDATE AtcUserStats SET dartsHit = :amount WHERE userName = :userName")
void UpdateHitAmount(int amount, String userName);
I have one repository which I assumed I use for all entities:
public class UsersRepository {
private UsersDao mUsersDao;
private AtcDao mAtcDao;
private LiveData<List<Users>> mAllUsers;
private LiveData<List<AtcUserStats>> mAllAtc;
private AtcUserStats mAtcUser;
UsersRepository(Application application) {
AppDatabase db = AppDatabase.getDatabase(application);
mUsersDao = db.usersDao();
mAtcDao = db.atcDao();
mAllUsers = mUsersDao.fetchAllUsers();
mAllAtc = mAtcDao.getAllAtcStats();
}
LiveData<List<Users>> getAllUsers() {
return mAllUsers;
}
LiveData<List<AtcUserStats>> getAllAtcStats() {
return mAllAtc;
}
LiveData<AtcUserStats> getAtcUser(String username) {
return mAtcDao.findByName(username);
}
public void insert (Users user) {
new insertAsyncTask(mUsersDao).execute(user);
}
public void insertAtc (AtcUserStats atc) {
new insertAsyncAtcTask(mAtcDao).execute(atc);
}
private static class insertAsyncTask extends AsyncTask<Users, Void, Void> {
private UsersDao mAsyncTaskDao;
insertAsyncTask(UsersDao dao) {
mAsyncTaskDao = dao;
}
#Override
protected Void doInBackground(final Users... params) {
mAsyncTaskDao.insertNewUser(params[0]);
return null;
}
}
private static class insertAsyncAtcTask extends AsyncTask<AtcUserStats, Void, Void> {
private AtcDao mAsyncTaskDao;
insertAsyncAtcTask(AtcDao dao) {
mAsyncTaskDao = dao;
}
#Override
protected Void doInBackground(final AtcUserStats... params) {
mAsyncTaskDao.insertNewAtcUser(params[0]);
return null;
}
}
}
My question is how do I create a AsyncTask for the update query I am trying to run in this repository?
Here is what I have so far by broadly copying the insert repository methods:
private class updateHitAsyncTask {
private AtcDao mAsyncTaskDao;
public updateHitAsyncTask(AtcDao mAtcDao) {
mAsyncTaskDao = mAtcDao;
}
protected Void doInBackground(int amount, String name) {
mAsyncTaskDao.UpdateHitAmount(amount, name);
return null;
}
}
Which is incorrect is that I'm getting a llegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time. error. But i thought this AsyncTask is suppose to take care of this?
Here is my update method in my view model, which is reporting 0 errors:
void updateHitAmount (int amount, String name) {
mRepository.updateAtcHits(amount, name);
}
and here is the UI code where im actually trying to tie all these together, I suspect there must be a better way that using onChanged for simply updating a field but again I am struggling to come across any advice on google with the repository approach:
private void callOnChanged() {
mAtcViewModel = ViewModelProviders.of(this).get(AtcViewModel.class);
mAtcViewModel.getAllUsers().observe(this, new Observer<List<AtcUserStats>>() {
#Override
public void onChanged(#Nullable final List<AtcUserStats> atc) {
// Update the cached copy of the users in the adapter.
for (int i = 0; i < atc.size(); i++) {
if (atc.get(i).getUserName().equals(mUser)) {
mAtcViewModel.updateHitAmount(55, mUser);
//atc.get(i).setDartsHit(55);
Log.d("id", String.valueOf(userSelected.getId()));
}
}
}
});
How can I update fields using this approach on the background thread?
Figured it out due to this answer here. It was mostly because of my lack of understanding of AsyncTask. Essentially I needed to create an object and pass the data that way and then execute in the background:
private static class MyTaskParams {
int amount;
String name;
MyTaskParams(int amount, String name) {
this.amount = amount;
this.name = name;
}
}
public void updateAtcHits (int amount, String name) {
MyTaskParams params = new MyTaskParams(amount,name);
new updateHitAsyncTask(mAtcDao).execute(params);
}
private class updateHitAsyncTask extends AsyncTask<MyTaskParams,Void,Void>{
private AtcDao mAsyncTaskDao;
public updateHitAsyncTask(AtcDao mAtcDao) {
mAsyncTaskDao = mAtcDao;
}
#Override
protected Void doInBackground(MyTaskParams... myTaskParams) {
int amount =myTaskParams[0].amount;
String name = myTaskParams[0].name;
mAsyncTaskDao.UpdateHitAmount(amount, name);
return null;
}
}

Reading an object from a Firebase database in android studio

Using Android Studio and Firebase, i'm trying to write and read some data.
I have a Pub Class which contains the folowing:
package com.example.jef.pubbuddy.Database;
import java.util.ArrayList;
public class Pub {
private String name;
private float longitude;
private float lattitude;
private ArrayList<Pub> Pubs = new ArrayList<>();
public Pub() {}
public void setName(String name)
{this.name = name;}
public void setLongitude(float longitude)
{this.longitude = longitude;}
public void setLatitude(float lattitude)
{this.lattitude = lattitude;}
public String getName()
{return name;}
public float getLatitude()
{return lattitude;}
public float getLongitude()
{return longitude;}
I write my Pub object to the database using the .push() method. Below is how i write it to the database. It appears just fine in the Firebase console, so I believe the problem doesn't lie here:
Pub p1 = new Pub();
p1.setName("The name of the pub");
p1.setLatitude((float) 4.699545);
p1.setLongitude((float) 50.878267);
myRef.child("PUSH_TEST").push().setValue(p1);
Afterwards I try to read it using the following code. Please note the message method is just used to append some information to a TextView, so i'm able to debug on my physical device. However, none of the listener events get triggered.
Does anyone knows what i'm doing wrong here? Already followed the official firebase documentation and the "Firebase in a weekend" training videos. Also looked up countless answers here on Stackoverflow, but I can't seem to make it work.
Thanks in advance.
public class Database extends AppCompatActivity {
private TextView tv;
int messages;
private ArrayList<Pub> pubList = new ArrayList();
private FirebaseDatabase database;
private DatabaseReference myRef;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_database);
database = FirebaseDatabase.getInstance();
myRef = database.getReference();
init();
writeData();
message("creating and attaching the listener");
ChildEventListener myListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s)
{
message("The childEvent triggered");
Pub p = dataSnapshot.getValue(Pub.class);
message("The name of this pub = " + p.getName());
pubList.add(p);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
myRef.child("PUSHTEST").addChildEventListener(myListener);
}
Everything is correct, except this:
Here you set the value:
myRef.child("PUSH_TEST").push().setValue(p1);
and here you retrieve the value:
myRef.child("PUSHTEST").addChildEventListener(myListener);
the child that you wrote is wrong as it is not in your database. So just change it into this:
myRef.child("PUSH_TEST").addChildEventListener(myListener);
the name inside child(..) needs to be the same as in your database
You write data to "PUSH_TEST" child and trying to read from "PUSHTEST". Make it same.
For not getting similar errors in future, create a class called "Constants.java" and add constant strings inside it. Like,
public class Constants {
public static final String CHILD_NODE="PUSH_TEST";
}
So that , you can use this constant, where ever u need. Just call Constants.CHILD_NODE. So there will not be such errors.

Realm findFirst() method returns null

I searched and found FindFirst returns null question but no one answered it. As I'm thinking I am doing something wrong, let me explain my problem with more details.
I'm working on an app that asks the user to sign in first and then lets the user use the app.
My User class looks like this:
public class User extends RealmObject {
#PrimaryKey
#SerializedName("uid")
String id;
#SerializedName("ufname")
String firstName;
#SerializedName("ulname")
String lastName;
String avatar;
int sessions;
int invites;
String nextSessionTime;
String nextSessionTitle;
#SerializedName("lastlogin")
String lastLogin;
String token;
#Override
public String toString() {
return new GsonBuilder().create().toJson(this, User.class);
}
// other setters and getters
}
I store User's object in Realm db after successful login in SigninActivity class:
#Override
public void onSignInResponse(final GeneralResponse response) {
if (response == null) {
Timber.e("response is null");
return;
}
Timber.d(response.toString());
if (response.isSuccess()) {
// Store user's info including Token
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
realm.copyToRealmOrUpdate(response.getUser());
}
});
// Goto main screen
MainVideoActivity.startActivity(this);
this.finish();
} else {
String errorMessage = response.getErrorMessages();
super.displayMessage(errorMessage);
}
}
Once the login is successful, app directs user to MainVideoActivity. I want to find user in realm by following code however I'm getting null.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_video);
// Create the Realm instance
realm = Realm.getDefaultInstance();
User user = realm.where(User.class).findFirst();
// RealmResults<User> user = realm.where(User.class).findAll();
Timber.d(user.toString());
}
user is null in both approaches.
However, I can see my none null user in db.
I'm using classpath "io.realm:realm-gradle-plugin:2.0.2"
There are two things here:
The null values in the debug window. That is a known limitation when using Realm with debugger. Since Realm generated a Proxy class to access values, inspecting the RealmObject's field in the debugger won't go through the proxy class. See more details here
The fields with null values are not printed in the toString() method. Realm annotation processor will generate a toString() method if there is no toString() method defined in the RealmObject. I think the problem here is the a User.toString() ignores null values. Try to remove the toString() method in the User class.
According Realm doc Realm you can try add isNotNull() in your query like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_video);
// Create the Realm instance
realm = Realm.getDefaultInstance();
User user = realm.where(User.class).isNotNull("id").findFirst(); //add in this line isNotNull()
//RealmResults<User> user = realm.where(User.class).findAll();
Timber.d(user.toString());
}
I have not tested yet, but it should work.
Try replacing
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
realm.copyToRealmOrUpdate(response.getUser());
}
});
// Goto main screen
MainVideoActivity.startActivity(this);
this.finish();
with
realm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
realm.copyToRealmOrUpdate(response.getUser());
}
}, new Realm.Transaction.OnSuccess() {
#Override
public void onSuccess() {
// Goto main screen
MainVideoActivity.startActivity(this);
finish();
}
});
One way to workaround this is to create an unmanaged copy of the object.
Replace:
User user = realm.where(User.class).findFirst();
with
User managed_user = realm.where(User.class).findFirst();
if(user!=null){
User unmanaged_user = realm.copyFromRealm(managed_user)
}
Return unmanaged_user.

Trying to get a value out of the OnPostExecute

i've got something blowing my mind all day long.
The question is, I have an AsyncTask that returns me an User Object, with all its attributes. I know that I have to return from the doInBackground method and receive in the OnPostExecute to work with my data. The fact is that i want to extract that user out of the AsyncTask method because i have to work with it in my main thread.
My AsyncTask class is placed in the MainActivity.class.
i've heard about using interfaces to get my value back but i can't understand the way to do it.
public class FetchUserDataAsyncTask extends AsyncTask<Void, Void, User> {
RequestHandler rh = new RequestHandler(); //this is the class i use to do de server conection
User user;
User ret_user;
public FetchUserDataAsyncTask(User user){
this.user = user;
}
#Override
protected void onPostExecute(User user) {
super.onPostExecute(user);
//I WANT THIS USER IN MY MAIN THREAD, TO WORK WITH ITS ATTRIBUTES
}
#Override
protected User doInBackground(Void... params) {
try {
HashMap<String, String> dataToSend = new HashMap<>();
dataToSend.put("username", user.username);
dataToSend.put("password", user.password);
ret_user = rh.sendGetRequest("myadresstophp.php", dataToSend);
} catch (Exception e) {
e.printStackTrace();
}
return ret_user;
}
and the call (when user press the log in button), a few lines above.
new FetchUserDataAsyncTask(userk).execute();
I was hoping to do something like that: (i know its not the way to do it)
User user = new FetchUserDataAsyncTask(userk).execute();
Thank you all, have a nice day!
At first declare an Interface in your project somewhere having the required functions, then implement that interface in the (AsyncTask)calling class ,then declare one Interface object in the AsyncTask. Create the constructor of AsyncTask as follows:
public FetchUserDataAsyncTask(User user,InterfaceClass object){
this.user = user;
this.interfaceObject=object;
}
And then do the following in onPostExecute:
#Override
protected void onPostExecute(User user) {
super.onPostExecute(user);
interfaceObject.function(user); //call the function of the calling class
}
You can create an interface, pass it toAsyncTask (in constructor), and then call method in onPostExecute()
For example:
Your interface:
public interface OnTaskCompleted{
void onTaskCompleted();
}
Your Activity:
public class YourActivity implements OnTaskCompleted{
// your Activity
}
And your AsyncTask:
public class YourTask extends AsyncTask<Object,Object,Object>{
//change Object to required type
private OnTaskCompleted listener;
public YourTask(OnTaskCompleted
listener){
this.listener=listener;
} // required methods
protected void onPostExecute(Object
o){
// your stuff
listener.onTaskCompleted();
}
}
Here you go, this is in general how it would work. This is based on this answer and modified to be specific to your existing code. Basically assign your member variable based on what the user entered, and compare that value to the one you get from the server:
public class MyClass extends Activity {
//member variable for the username the user enters:
User userEnteredUser;
public class FetchUserDataAsyncTask extends AsyncTask<Void, Void, User> {
RequestHandler rh = new RequestHandler(); //this is the class i use to do de server conection
User user;
User ret_user;
public FetchUserDataAsyncTask(User user){
this.user = user;
}
#Override
protected void onPostExecute(User user) {
super.onPostExecute(user);
//I WANT THIS USER IN MY MAIN THREAD, TO WORK WITH ITS ATTRIBUTES
processValue(user); //added
}
#Override
protected User doInBackground(Void... params) {
try {
HashMap<String, String> dataToSend = new HashMap<>();
dataToSend.put("username", user.username);
dataToSend.put("password", user.password);
ret_user = rh.sendGetRequest("myadresstophp.php", dataToSend);
} catch (Exception e) {
e.printStackTrace();
}
return ret_user;
}
}
private void getValue()
{
EditText et = (EditText) findViewById(R.id.username);
userEnteredUser.username = et.getText().toString(); //something like this.... replace with your syntax
new FetchUserDataAsyncTask(userEnteredUser).execute();
}
private void processValue(User userFromServer)
{
if (userEnteredUser.equals(userFromServer)) {
//Users match! Yay!
}
}
}
onPostExecute runs on the UI thread by default (main thread). Do what ever you need to be do on the main thread in onPostExecute
I suggest you read up more from the link provided below for a better understanding on AsyncTask
http://developer.android.com/reference/android/os/AsyncTask.html
I'm uncertain what you mean by "main thread". If you mean "UI Thread", which is the primary thread used to execute in your app, then Shashank's reply is correct.
However, I suspect from the context of the question that you actually mean that you want the results returned to the code that initiated the AsyncTask. Let's call that the "invoking object" In that case, what I would do is define a callback in your invoking object whose only purpose is to receive the result of this AsyncTank. You could call it onUserDataFetched(User user).
So, to do this using Interfaces, you could define an Interface that contains a single method:
public interface FetchUserDataListener {
public void onUserDataFetched(User user);
}
Then make sure that your InvokingObject implements that interface, and pass your InvokingObject (which implements FetchUserData, and thus can be considered that object type) to your AsyncTask when you instantiate it.
So, you invoking object code would look like this:
public class InvokingObject implements FetchUserData {
public void someMethodToInvokeFetchUserData() {
//....
new FetchUserDataAsyncTask(userk, this).execute();
//....
}
#Override
public void onUserDataFetched(User user) {
//Compare the result to the data in your invoking object
}
}
Then pass that callback to your AsyncTask when you construct it:
And your AsyncTask Code would look like this:
public class FetchUserDataAsyncTask extends AsyncTask<Void, Void, User> {
FetchUserDataListener mFetchUserDataListener;
public FetchUserDataAsyncTask(User user, FetchUserDataListener listner){
this.user = user;
mFetchUserDataListener = listener
}
//...
#Override
protected void onPostExecute(User user) {
super.onPostExecute(user);
listener.onUserDataFetched(user)
}
//...
}

Categories

Resources