I made this post because I don't understand how transaction works using GreenDao and I would love to get some explanation/recent tutorial.
Despite of reading the Greendao github, I don't understand how the main activity works. For example:
...
Note note = new Note(null, noteText, comment, new Date(), NoteType.TEXT);
noteDao.insert(note)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Note>() {
#Override
public void call(Note note) {
Log.d("DaoExample", "Inserted new note, ID: " + note.getId());
updateNotes();
}
});
...
Do the observeOn method sends every insertion/update to one limited buffer? so, it will manage automatically the insertion to the real database when every operation was finished whithout problems?
Reading its API, we could see that they use rxTx and rxTxPlain for transactions (other way?), and finding out where are performed, I have to say I misunderstood everything. For example:
...
public void testConcurrentInsertDuringTx() throws InterruptedException {
...
Runnable runnable2 = new Runnable() {
#Override
public void run() {
dao.insertInTx(createEntity(null));
}
};
Runnable runnable3 = new Runnable() {
#Override
public void run() {
daoSession.runInTx(new Runnable() {
#Override
public void run() {
dao.insert(createEntity(null));
}
});
}
};
...
// Builds the statement so it is ready immediately in the thread
dao.insert(createEntity(null));
doTx(new Runnable() {
#Override
public void run() {
dao.insert(createEntity(null));
}
});
latchThreadsDone.await();
assertEquals(7, dao.count());
}
...
I know this is an example, but I don't know the diferences of using the rx methods and the observeOn/subscribe ones
protected void doTx(final Runnable runnableInsideTx) {
daoSession.runInTx(new Runnable() {
#Override
public void run() {
latchInsideTx.countDown();
// Give the concurrent thread time so it will try to acquire locks
try {
Thread.sleep(TIME_TO_WAIT_FOR_THREAD);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
runnableInsideTx.run();
}
});
}
I read some topics about transactions, but they are obsoletes or maybe, I didn't understand them correctly:
SQLite transaction behaviour using greendao
Android - Green Dao Multiple Transaction
Transactions in GreenDao
greenDAO 40 seconds to insert 600 records
https://groups.google.com/forum/#!topic/greendao/PXRwCRTbP6c
Someone could help me giving me some explanation/recent tutorial? Greendao have these methods as experimentals. Thanks in advance
Related
I am using retrofit and Rxjava to handle api calls for my mvvm android application. Based on some tutorial, i am currently using RxJava like this.
ViewModel.java
CompositeDisposable disposable = new CompositeDisposable();
private void fetchTodolist(){
loading.setValue(true);
disposable.add(
service.getToDoList("A1833")
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableSingleObserver<ApiResponse<ArrayList<TodoItem>>>() {
#Override
public void onSuccess(ApiResponse<ArrayList<TodoItem>> value) {
if(value.getStatus() == 200){
//on call success code
} else {
//on call rejected code
}
}
#Override
public void onError(Throwable e) {
// on call error code
}
})
);
}
And now i want to cache the result of the api call on successful call into room database. So i need to use another async method and tried to reuse the new thread i created before. And here's the code.
private void fetchTodolist(){
loading.setValue(true);
Scheduler a = Schedulers.newThread();
disposable.add(
service.getToDoList("A1833")
.subscribeOn(a)
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableSingleObserver<ApiResponse<ArrayList<TodoItem>>>() {
#Override
public void onSuccess(ApiResponse<ArrayList<TodoItem>> value) {
if(value.getStatus() == 200){
a.scheduleDirect(new Runnable() {
#Override
public void run() {
long inserted = dao.insert(value);
}
});
} else {
//on call rejected code
}
}
#Override
public void onError(Throwable e) {
// on call error code
}
})
);
}
I wonder if it is a bad practice and will lead to a serious problem. And if so, what's the alternative.
Schedulers uses cached references thus newThread() returns the same Scheduler instance.
Schedulers.newThread() == Schedulers.newThread()
Generally you should avoid using newThread because it creates a new thread for every application of the operator. So if you run the sequence multiple times, new worker threads are created and dismissed without any kind of reuse. This is especially true for newThread().scheduleDirect which will start a new thread just for that single runnable and stop it afterwards.
It is recommended you use Schedulers.io() for IO operations so that those underlying worker threads are reused as much as possible later.
I have two or more network calls in separated threads on main activity start, I want to show all data after network threads done.
Thread firstNetworkCallThread=new Thread(new Runnable() {
#Override
public void run() {
// network calls and get data...
}
});
Thread secondNetworkCallThread =new Thread(new Runnable() {
#Override
public void run() {
// network calls and get data...
}
});
firstNetworkCallThread.start();
secondNetworkCallThread.start();
I want these threads work parallel, and when both of them are complete, call new event to show data.
How can I do this?
Guava has a good solution for this. If you convert your Threads to ListenableFutures (also a Guava object) you can create a list of ListenableFutures and add a callback to that list.
Futures.addCallback(
Futures.allAsList(/*future1*/, /*future2*/, /*future3*/),
new AbstractDisposableFutureCallback<List<Object>>() {
#Override
protected void onSuccessfulResult(List<Object> results) {
// whatever should happen on success
}
#Override
protected void onNonCancellationFailure(Throwable throwable) {
// whatever should happen on failure
}
});
Guava also has a bunch methods such as #successfulAsList which only contains successful results or #inCompletionOrder which orders them based on when they completed and a bunch of others.
I generally tend to use Guava as it provides a fairly clean solutions to problems like these.
An example of how to creates a ListenableFuture is as follows:
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture<Object> explosion =
service.submit(
new Callable<Object>() {
public Object call() {
// get network data
return null; // return the data
}
});
In my Android project i use Azure Mobile Services SDK and the way i make queries to the local sqlite database is like the following:
(example taken from http://azure.microsoft.com/en-us/documentation/articles/mobile-services-android-get-started-data/).
The problem is that i get the following errors:
1)com.microsoft.windowsazure.mobileservices.table.sync.localstore.MobileServiceLocalStoreException: java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed
2) A SQLiteConnection object for database 'LocalDatabase' was leaked! Please fix your application to end transactions in progress properly and to close the database when it is no longer needed
3) java.util.concurrent.ExecutionException: com.microsoft.windowsazure.mobileservices.table.sync.localstore.MobileServiceLocalStoreException: java.lang.IllegalStateException: attempt to re-open an already-closed object
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
try {
final MobileServiceList<ToDoItem> result = mToDoTable.where().field("complete").eq(false).execute().get();
runOnUiThread(new Runnable() {
#Override
public void run() {
mAdapter.clear();
for (ToDoItem item : result) {
mAdapter.add(item);
}
}
});
} catch (Exception exception) {
createAndShowDialog(exception, "Error");
}
return null;
}
}.execute();
In this implementation there is no Cursor or SQLiteOpenHelper object to close. What could i do?
Thank you!
I think this is because you are getting the result in one thread but trying to use that same result in the UI thread. One possible method is to use Broadcast or Eventbus to send the data back to the UI once the operation completes:
Here is sort of what I would do:
Futures.addCallback(mToDoTable.where().field("complete").eq(false).execute(), new FutureCallback() {
#Override
public void onSuccess(Object result) {
//Do something with result
//I would use event bus or broadcast here to notify the UI
}
#Override
public void onFailure(Throwable t) {
}
});
If this doesn't work, I would use the debugger and put a break point on that execute().get() line and see what is happening internally.
Here is another possible way to do it:
mToDoTable.where().field("complete").eq(false).execute(new TableQueryCallback<Object>() {
#Override
public void onCompleted(List result, int count, Exception exception, ServiceFilterResponse response) {
}
});
I have an app that runs 2 threads in loops. 1st one is updating a graph in 1s interval and the second one is updating another graph at 60s interval. The second task is taking a long time since it is quering some server in the internet 3 times that might not always be available and even if it is it will take up to 5-7s to execute.
What is happening is when I launch the second thread it will pause execution of the first one and that is not what I want, I wish both run concurrently. Here in the Youtube video you can see the results of the app running. http://youtu.be/l7K5zSWzlxI
"thread_updater1s" is running a green graph, large readout, and a timer in the corner so you clearly see it stalls for 11 seconds.
1)First of all why is that happening? how to fix it?
2)I'm aware that I might not launch the threads properly at all. I had hard time understanding how to make something to run in a interval loop in Java and my code worked fine for one graph/tread. Now when I have 2 loops in separate threads I don't know why they are not executing concurrently.
Here is the code:
public class LoopExampleActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
thread_updater1s.start();
thread_updater2.start();
}// end of onCreate
final Runnable r1s = new Runnable() {
public void run() {
do_1s_updates(); // those are very quick http calls to the local API server
} // to get data nessessary for some plot.
// They have 1s timeout as well but rarely timeout
};
final Runnable r2 = new Runnable() {
public void run() {
do_large_updates(); //This makes 7 long call over the Internet to the slow https
//server once every 60s. Has 10s timeout and sometimes takes as much as
//7s to execute
}
};
Thread thread_updater1s = new Thread() {
#Override
public void run() {
try {
while (true) {
handler.post(r1s);
sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread_updater2 = new Thread() {
#Override
public void run() {
try {
while (true) {
handler2.post(r2);
sleep(60000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
PS. please be forgiving and informative I only code Java for 15 days so far with absolutely no prior experince or lesson.
You need to make the http requests in the threads (not the posted runnables). Then, when you have the data downloaded, you create a runnable with that data that will update the graph and post that runnable to be executed by the UI thread. Here is an example:
public class LoopExampleActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
thread_updater1s.start();
thread_updater2.start();
}// end of onCreate
Thread thread_updater1s = new Thread() {
#Override
public void run() {
try {
while (true) {
final Object data = getDataFromServer1();
handler.post(new Runnable() {
#Override
public void run() {
updateGraph1(data);
}
);
sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread_updater2 = new Thread() {
#Override
public void run() {
try {
while (true) {
final Object data = getDataFromServer2();
handler.post(new Runnable() {
#Override
public void run() {
updateGraph2(data);
}
);
sleep(60000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Obviously, change that final Object data by the appropriate class that represents your data downloaded.
handler.post pushes the runnable onto the main (UI) thread's message queue for execution on the main thread.
So what you're doing is every sleep interval, you're sending a message to the main thread to run the function. Clearly, the main thread can't run 2 things at once, so that's why one runnable is delayed for the next one.
You probably want to do the work of the runnable in the separate threads - why did you start using a handler? What happens if you call do_1s_updates and do_large_updates directly instead of through the handler & runnable?
I have listed of products with different category. I have to sort them. Because of the queries, It is taking more time to load. Between two activities, the screen is coming black. I want to run the query in the background. How can I do that and how to use its result in main activity?
private class InsertTask extends AsyncTask {
String cat;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Boolean doInBackground(String... params) {
Boolean success = false;
try {
category(cat);
success = true;
} catch (Exception e) {
if(e.getMessage()!=null)
e.printStackTrace();
}
return success;
}
#Override
protected void onPostExecute(Boolean success) {
super.onPostExecute(success);
}
private void category(String category) {
try{
Cursor1 = mDbHelper.fetchcategory(category);
}catch(Exception e){
Log.v("Excep", ""+e);
}
}
And when called
InsertTask task = new InsertTask();
task.execute();
I have listed the category in buttons. How can I get the values then?
You should use AsyncTask for that. And some more info.
Its good you have thought of AsyncTask. Firstly, you can declare this class as inner in you class activity (if you haven't previously did) and so you are able to access you view class members.
You can do this also by creating thread and one handler that will be used to update your UI components. Remember that if you use threads you'll need to lock/unlock your database object because of the thread safety(if any other thread is accessing the database for any reason). Read more about thread safety of dbs.
I was doing some searching myself, and I came across this read, its rather long but looks extremely helpful, with lots of code examples. (I bookmarked it for myself).
Threads, Async, and Handlers O MY!
But some form of threading is the ticket.
From Android dev.
(My favorite code snippet)
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
//Do Work here
}
}).start();
}