I need a safe practise to load data from the Database.
I need to load the data from the Sql db and put it into a list or recylerview.
So what i tryied, i created a class which call the method load more everytime when user reaches the end of the list. And than it load the data limited.
Like 'Select * From a Where 1 Limit listItemCount, 20'.
I run into problems with this because, the thread which was loading, started 2 times with the same count value. Than i have changed it to synch the global run method from the loading thread. And accessing the count from the background worker of the list. This helped me a lot, and the data was loaded correctly, but i got still troubles with this. Because i need to insert the data into listview from the background thread, because of the synchronisation and calling notify in main thread after. If i am not doing it like this, i will get still problem.
Thread A: Started work.
Thread B: Waiting for finishing thread A (synchronized)
Thread A: runOnUiThread() trying to fill data.
Thread B: Allowed to run the code, getting count from listView.
Thread B: Got the same count as A, because A not finished the insert
statement.
Thread A: Added data.
Thread B: Added same data.
After this i added a atomicboolean, that if the thread is running he is just not executed. With this it was working perfect, but sometimes you have to scroll up a bit and down to trigger the load more.
And i think this solution is a bit dirty for me. Anyone now how to load data in pieces depending on list size of the listview, in a background thread without this issues?
This method is getting called when reaching the end of list:
private ExecutorService executorService;
private void loadMore()
{
if(!isAdded())
return;
if(executorService == null)
executorService = Executors.newSingleThreadExecutor();
executorService.execute(new AsyncLoadMoreHashTags(getContext(), this, esaphTagAdapterVertical));
}
Background Thread:
public class AsyncLoadMoreHashTags extends MyDataLoaderClass
{
private static final Object obLock = new Object();
public AsyncLoadMoreHashTags(Context context, DataBaseLoadWaiter dataBaseLoadWaiter, SpecialRecylerView spRecylerView)
{
super(context, dataBaseLoadWaiter, spRecylerView);
}
#Override
public void run()
{
super.run();
synchronized (AsyncLoadMoreHashTags.obLock)
{
List<Object> objectList = null;
try
{
int startFrom = super.getStartFrom()[0];
SQLHashtags sqlHashtags = new SQLHashtags(super.getSoftReferenceContext().get());
if(startFrom <= 0)
{
objectList = sqlHashtags.getMostUsedHashtags();
}
else
{
objectList = sqlHashtags.getAllHashtagLimited(startFrom);
}
sqlHashtags.close();
}
catch (Exception ec)
{
Log.i(getClass().getName(), "AsyncLoadMoreHashTags run() failed: " + ec);
}
finally
{
publish(objectList);
}
}
}
}
What i need is to, just start one thread a time.
Anyone a idea?
First of all use You should have to use PagedList library provided by google, for implementing paging facility, and if you want to use background thread for database operations you can use Anko commons to do this. Here is an example,
internal val pagedList by lazy {
runBlocking { // Coroutine Context
withContext(Dispatchers.IO) {
// Read from database, and it will be initialised in background
}
}
}
and if you want something to be dispatched on UI but performed in Background Thread, then go with this, doAsync operation and then return data in uiThread by using a custom interface.
doAsync {
// LONG OPERATION
Thread.sleep(2000)
uiThread {
callback.onActionsDone(dataList)
}
}
Let me know if you want more help on this.
Fixed it with like this, working fine.
public class AsyncLoadMoreHashTags extends OwnDataLoader
{
private static AtomicBoolean obLock = new AtomicBoolean(false);
public AsyncLoadMoreHashTags(Context context, DataBaseLoadWaiter dataBaseLoadWaiter, MomentsRecylerView momentsRecylerView)
{
super(context, dataBaseLoadWaiter, momentsRecylerView);
}
#Override
public void run()
{
super.run();
if(!AsyncLoadMoreHashTags.obLock.compareAndSet(false, true)) //when any thread loading data, its return and skips.
return;
List<Object> objectList = null;
try
{
int startFrom = super.getStartFrom()[0];
SQLHashtags sqlHashtags = new SQLHashtags(super.getSoftReferenceContext().get());
if(startFrom <= 0)
{
objectList = sqlHashtags.getMostUsedHashtags();
}
else
{
objectList = sqlHashtags.getAllHashtagLimited(startFrom);
}
sqlHashtags.close();
System.out.println("TEST: " + startFrom + " LOAD: " + objectList.size());
}
catch (Exception ec)
{
Log.i(getClass().getName(), "AsyncLoadMoreHashTags run() failed: " + ec);
}
finally
{
publish(objectList, AsyncLoadMoreHashTags.obLock); //Passing the lock object, when data has been added, obLock.set(false); is called.
}
}
}
Related
In android, there are many async APIs such as WebView's evaluateJavascript, which will Asynchronously evaluates JavaScript in the context of the currently displayed page. Usually an execution will just proceed to the successive statements after the call of an async API without any waiting.
But how can I wait until this call finishes its executing, before proceeding to the successive statements. For example,
webview.evaluateJavascript("JS code", new ValueCallback<String> {
public void onReceiveValue(String value) {
//get JS return here
}
});
//Remaining code
How can I make sure the remaining code is executed after webview.evaluateJavascript has finished its executing (i.e., its callback onReceiveValue has finished its executing).
Edit: To be more precise, what I want is that remaining code should be executed after onReceiveValue has finished executing.
I find out a workaround by using JavaScript interface. The idea is that we create a bridge class that contains a method that takes the javascript execution result as input. Then we can obtain the result at the Java end. This method works because bridge methods are invoked by JavaScript code, which is run on another thread. We only need to wait on the UI thread for a little milliseconds, then the result is here for you. The following code is an illustration:
class Bridge {
public String result = null;
#JavascriptInterface
public void putJsResult(String result) {
this.result = result;
}
public String getJsResult() {
return this.result;
}
}
Bridge bridge = new Bridge();
wv.addJavascriptInterface(bridge, "bridge");
webview.evaluateJavascript("bridge.putJsResult(func())", null);
Thread.sleep(100);
//Result is there
String result = bridge.getJsResult();
When you have to wait for code execution, a simple class to use is CountDownLatch.
An example for your problem can be:
public class AboutActivity extends Activity {
private volatile CountDownLatch jsLatch = new CountDownLatch(1);
private volatile String jsReceivedValue = null
initWebView() {
// webview init
...
webview.evaluateJavascript("JS code", new ValueCallback<String> {
public void onReceiveValue(String value) {
//get JS return here
jsReceivedValue = value
jsLatch.countDown();
}
});
try {
// wait 60 seconds or assume there was some problem during the loading
jsLatch.await(60, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// thread interrupted or time elapsed
}
if (jsReceivedValue == null) {
// show "problem during loading"
} else {
//Remaining code
}
}
}
Note that waiting for code execution on main thread, can lead to unresponsive app.
You can show a loading spinner while using a simple thread to avoid this:
new Thread(new Runnable() {
#Override
public void run() {
initWebView();
}
}).start();
I want to save all the messages received in the onMessageReceived of the service inside a SQLite db.
I was planning to open the db, insert the data and close the db. This would work well with an intent service as all the calls to the onMessageReceived would be queued and thus execute one by one.
However if the onMessageReceived gets called concurrently for multiple messages, it could cause issues of the Db being closed while another call is trying to write thus leading to issues.
Can anyone confirm what kind of behaviour i should expect.
If it is not an intent service, i might have to look at the DB singleton pattern and synchronization blocks
Currently, FirebaseMessagingService extends Service directly, so it is not an IntentService.
Source
Snapshot:
You can check LinkedBlockingDeque<> class which queues your requests and can be performed in background sequentially.
Check below sample class of mine -
public class Processor implements Runnable {
private final LinkedBlockingDeque<Task> mTaskQueue = new LinkedBlockingDeque<Task>();
private boolean mExecuteTask = true;
#Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
// You can put some end condition if needed
while (mExecuteTask) {
Task task;
try {
// Waits if necessary until an element becomes available
task = (Task) mTaskQueue.take();
} catch (InterruptedException e) {
continue; // re-test the condition on the eclosing while
}
if (task != null) {
task.runnable.run();
}
}
}
// Call this method to put Runnable in Queue.
public synchronized void put(int id, Runnable runnable) {
try {
Task task = new Task();
task.runnable = runnable;
task.id = id; // someUniqueId to avoid duplication
// Check Id of tasks already present in Queue
mTaskQueue.addLast(task);
} catch (IllegalStateException ie) {
throw new Error(ie);
}
}
private static class Task {
public Runnable runnable;
// Unique Id of task
public int id;
}
}
I have over 10 fragments that execute the same kind of task which is :
Retrieving the Data from the server using Retrofit
Starting an Async Task to update the Database (Using ORMLite)
Once the Database is updated, retrieving the new data from the Database
Notify Dataset has changed in the adapter
I'm wondering if it's useless to put the update database code inside an AsyncTask within my fragment once I retrieve the data from the server?
I have trouble understanding what run on the UI thread and what doesn't and should be started as his own thread through an AsyncTask
Here my code:
private void getLocalIncidentTemplate() {
mIncidentTemplate.clear();
mIncidentTemplate.addAll(GenericDAO.getInstance(EntityGroup.class).queryForAll());
Collections.sort(mIncidentTemplate);
Log.e(TAG, "Incident Template count:" + mIncidentTemplate.size());
mListAdapter.notifyDataSetChanged();
spinner.setVisibility(View.GONE);
}
private void getRemoteIncidentTemplate() {
Call<EntityIncident> call = meepServices.getIncidentTemplate();
call.enqueue(new Callback<EntityIncident>() {
#Override
public void onResponse(Call<EntityIncident> call, Response<EntityIncident> response) {
if (response.isSuccessful()) {
new updateIncidentTemplateTask().execute(response.body());
}
}
#Override
public void onFailure(Call<EntityIncident> call, Throwable t) {
t.getStackTrace();
Log.e(TAG, t.toString());
Utils.showToastMessage(getActivity(), "Error retrieving Incidents", true);
}
});
}
private class updateIncidentTemplateTask extends AsyncTask<EntityCategories, Void, Boolean> {
#Override
protected Boolean doInBackground(EntityCategories... params) {
updateIncidents(params[0]);
return true;
}
protected void onPostExecute(Boolean b) {
getLocalIncidentTemplate();
spinner.setVisibility(View.GONE);
}
}
Here is the Database Update Using ORMlite:
private void updateIncident(EntityCategories categories) {
try {
categories.setId("MobilePlan");
//Update base categories
GenericDAO.getInstance(EntityCategories.class).addOrUpdate(categories);
for (EntityCategories.EntityCategory currentCategory : new ArrayList<>(categories.getCategories())) {
if (currentCategory.getmPlans() != null) {
for (EntityPlan myPlan : new ArrayList<>(currentCategory.getmPlans())) {
EntityPlan oldPlan = GenericDAO.getInstance(EntityPlan.class).queryById(String.valueOf(myPlan.getmId()));
myPlan.setCategories(currentCategory);
if (oldPlan != null) {
if (!myPlan.getmDateModification().equals(oldPlan.getmDateModification())) {
GenericDAO.getInstance(EntityPlan.class).addOrUpdate(myPlan);
}
} else {
GenericDAO.getInstance(EntityPlan.class).addOrUpdate(myPlan);
}
}
} else {
continue;
}
GenericDAO.getInstance(EntityLabel.class).addOrUpdate(currentCategory.getmLabel());
currentCategory.setCategories(categories);
GenericDAO.getInstance(EntityCategories.EntityCategory.class).addOrUpdate(currentCategory);
}
} catch (Exception e) {
e.printStackTrace();
}
Log.d(TAG, "DATA updated");
}
For your particular case, you should use the AsyncTask to retrieve data from the backend and place it in the database.
Remember that AsyncTask has three main methods:
onPreExecute() that runs on the UI thread. Useful when you need to prep something that requires UI thread (touching views and whatnot)
doInBackGround() this runs on background thread
onPostExecute() runs also on the UI thread.
In onPostExecute() you could notify your adapter of the new data.
If I were you, I'd use loaders to get notified and retrieve the data off the database. So that the complete chain would be some:
AsyncTask pulls data from the backend and stores it in the database
Your loader will get notified that something changed inside the database and will pull the data from it and call onLoadFinished() method inside your activity/fragment
onLoadFinished() passes the data to the view adapter.
I haven't gone into detail as to how to implement this. I just presented the overall architecture.
I have trouble understanding what run on the UI thread and what doesn't and should be started as his own thread
The short answer:
Everything that might block the UI thread (in other words, might take time) should run on a worker thread (threadpool or dedicated)
DB actions and network requests are classic examples for actions that should always run asynchronously.
In your case I would just use an ORM to wrap all the interaction with the DB, such as ORMlite or any other you find more suitable, in that case you will not have to concern yourself with the inner workings and just provide callbacks for when your calls have finished (successfully or not)
Currently I am trying to collect location updates periodically, say for every 10 samples. I am using an arraylist to collect them and clear off the arraylist in the main UI thread once I passed them to the server using async task. In the async task I am loading the arraylist with the one from main UI.
The problem is, it is clearing the arraylist in the async task even it is in separate variable. How can I keep the activity in sync. Do I need to sleep the main activity till the async task finishes. I am not sure about the variable. Can someone explain how to do this?
MainMapActivity(X){
locationupdate for every 1 min{
arraylist a;//this collects all location updates 10 samples each time
call asynctask b;
clear a;
}
asynctask b{
arraylist c = getall from a;
db= insert(c);//save a into database;
}
Clearing a in main UI clears of variable c. How can I prevent that? The variable c should be only cleared after saving all the data in it.
If I'm getting what you are trying to say is,then yes, we have a way to fix your problem using handlers.
In your async task, do something like this -
private mLocations;
public MyTask(Handler mResponseHandler, List<Location> mLocations){
super();
this.mLocations = mLocations;
this.mResponseHandler = mResponseHandler;
}
in onPostExecute,
onPostExecute(List<Location>){
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
Log.i(TAG, "result = "+result);
if (mResponseHandler == null) return;
MyLocationData<Location> resultData = new MyLocationData<Location>();
if(result != null && result){
resultData.requestSuccessful = true;
resultData.responseErrorCode = 0;
}else{
resultData.requestSuccessful = false;
resultData.responseErrorCode = errorCode; //set this when result is null
}
android.os.Message m = android.os.Message.obtain();
m.obj = resultData;
mResponseHandler.sendMessage(m);
}
}
Where MyLocationData is a model class in which I'm saving all relevant data. It can be a class like this -
public class MyLocationData<Type> {
public Type response;
public int responseErrorCode;
public boolean requestSuccessful;
}
Now, in your activity, you can get this data like,
private Handler mExportHandler = new Handler(){
public void handleMessage(android.os.Message msg) {
MyLocationData<Location> responseData = (MyLocationData<Location>) msg.obj;
// your logic for fetching new locations from responseData and using them in your activity
};
};
I need to perform a series of http requests, each of which may depend on a previous http response. I have been able to achieve this using an AsyncTask "tree" of sorts, but as the decision tree grows, the AsyncTask technique grows more unwieldy.
I think that somehow using a SynchronousQueue (or other type of queue) is the best approach, but I can't seem to find any good guidance or tutorials on how to use a Queue for something like http requests.
Can anyone provide any guidance or point to any good tutorials on using SynchronousQueue or suggest the best kind of Queue?
Use a java.util.concurrent.SingleThreadExecutor and make a Runnable out of each HTTP operation and result-handler. You can submit subsequent tasks to it as you determine whether you need to continue progress.
For example, the HTTP "task" would run and submit the Result "task" on success, or the Error "task" on failure. The Result task would in-turn submit another HTTP task when it was done processing. Using SingleThreadExecutor ensures only one task runs at-a-time.
You could use a ThreadPoolExecutor if you can handle multiple operations in-flight at once.
Take all that, and wrap it in an AsyncTask that manages the top-level "kick-off" and waits for everything to complete. It would probably be useful to have a ConditionVariable or something to synchronize the "end" signal (using a Done "task") so you can safely tear down the Executor.
A SynchronousQueue doesn't do anything helpful for you here, because it leaves you to do all the tread management. If you use an Executor that is all handled and all you deal with is Runnables and Futures. That's probably why you are not finding any tutorials. Anyway, the Executors all use one of those queue implementations underneath!
As requested, here is some skeleton Java code. Unsupported untested as-is. This should get you started. You can use a different synchronization object if you don't like ConditionVariable.
This is a generic technique, not specific to Android, feel free to use it in other contexts.
This functions as a State Machine, with HttpTask et al forming the states, and the transitions are hard-coded by submitting the Next State to the ExecutorService. There's even a "Big Bang at the end, so everyone knows when to clap" in the form of the ConditionVariable.
Some may consider DoneTask and FailedTask overkill, but it keeps the Next State mechanism consistent, and lets Future<? extends ResultTask> function as a somewhat type-safe container for the results, and certainly keeps you from mis-assigning to it.
abstract class BasicTask {
final ExecutorService es;
final ConditionVariable cv;
public BasicTask(ExecutorService es, ConditionVariable cv) {
this.es = es;
this.cv = cv;
}
}
abstract class HttpTask extends BasicTask {
// source omitted.
// you should make a class to prepare e.g. Apache HTTP resources for specific tasks (see below).
}
abstract class ResultTask implements Runnable {
final ConditionVariable cv;
public ResultTask(ConditionVariable cv) {
this.cv = cv;
}
public void run() {
cv.open();
}
}
final class FailedTask extends ResultTask {
final Exception ex;
public FailedTask(ConditionVariable cv, Exception ex) {
super(cv);
this.ex = ex;
}
public Exception getError() { return ex; }
}
final class DoneTask<T> extends ResultTask {
final T results;
public DoneTask(ConditionVariable cv, T results) {
super(cv);
this.results = results;
}
public T getResults() { return results; }
}
class HttpSequence extends AsyncTask<Void,Void,Object> {
// this will capture the ending task
Future<? extends ResultTask> result;
// this is an inner class, in order to set Result. Refactor so these are small.
// if you don't like inner classes, you still need to arrange for capturing the "answer"
final class SomeHttpTask extends HttpTask implements Runnable {
public void run() {
try {
final SomeType thisStep = doTheStuff(lastStep);
if(thisStep.isDone()) {
// we are done here
result = es.submit(new DoneTask<SomeType>(cv, thisStep));
}
else if(thisStep.isFailed()) {
// not done: we can't proceed because of something in the response
throw thisStep.getError();
}
else {
// not done, everything is ok for next step
es.submit(new NextHttpTask(es, cv, thisStep));
}
}
catch(Exception ex) {
result = es.submit(new FailedTask(cv, ex));
}
}
}
final class TheFirstTask extends HttpTask implements Runnable {
// source omitted. just emphasizing you need one of these for each "step".
// if you don't need to set Result, this could be a static inner class.
}
#Override
public Object doInBackground(Void...) {
final ExecutorService es = Executors.newSingleThreadExecutor();
final ConditionVariable cv = new ConditionVariable(false);
try {
es.submit(new TheFirstTask(es, cv));
// you can choose not to timeout at this level and simply block until something happens...
final boolean done = cv.block(timeout);
if(!done) {
// you will need to account for unfinished threads, see finally section!
return new IllegalStateException("timed out waiting on completion!");
}
if(result != null) {
final ResultTask done = result.get();
if(done instanceof DoneTask) {
// pass SomeType to onPostExecute()
return ((DoneTask<SomeTYpe>)done).getResults();
}
else if(done instanceof FailedTask) {
// pass Exception to onPostExecute()
return ((FailedTask)done).getError();
}
else {
// something bad happened, pass it to onPostExecute()
return new IllegalStateException("something unexpected signalled CV!");
}
}
else {
// something bad happened, pass it to onPostExecute()
return new IllegalStateException("something signalled CV without setting result!");
}
}
catch(Exception ex) {
// something outside workflow failed, pass it to onPostExecute()
return ex;
}
finally {
// naive shutdown (doesn't interrupt running tasks): read JavaDoc on ExecutorService for details
es.shutdown();
}
}
#Override
public void onPostExecute(Object result) {
if(result instanceof SomeType) {
// success UI
}
else if(result instanceof Exception) {
// error UI
}
}
}
I can't say for sure without knowing the details of your use case, but you probably want to avoid the SynchronousQueue, as it will block the thread putting things into the queue until the listener thread takes it back out of the queue. If you were putting things in using the UI thread you'd be locking up the UI.
I think a BlockingQueue may suit your needs. The JavaDoc has a good producer-consumer example.