Duplication of threads? - android

I am implementing one app related to alaram manager and brodcastreceivers.
I am repeting alarm in every minute,through the alarm manager I call brodcastresever class.
In side this class I am implementing one thread. The code is as follows:
runnable = new Runnable()
{
public void run()
{
while(i>o)
{
}
}
if i>o the thread will continue.
Another time my alaram manager call brodcast resever class. That time also one new thread is created with old thread. This increases duplication of threads.
How to avoid that?

Why not you use a queue of requests to process instead of creating new thread every time. Like:
if(queue==null)
{
queue= new ArrayList<Request>();
queue.add(request);
start();
}
public void run()
{
while(queue!=null && queue.size()>0)
{
Request request= fetchRequest();
processRequest(request);
}
}
private Request fetchRequest()
{
Request request=queue.get(0);
queue.remove(0);
if(queue.size()==0)
queue=null;
return request;
}
Note its just a prototype, not implementation.

Related

Thread.sleep() vs handler.postDelay() to execute network call in every 30sec

I want perform a network call in every 30sec to push some metrics to Server. Currently I am doing it using thread.sleep(). I found some articles saying thread.sleep() has some drawbacks. I need to know am I doing it right? or Replacing the thread with Handler will improve my code?
public static void startSending(final Context con) {
if (running) return;
running = true;
threadToSendUXMetrics = new Thread(new Runnable() {
#Override
public void run() {
do {
try {
Thread.sleep(AugmedixConstants.glassLogsPushInterval);
} catch (InterruptedException e) {
mLogger.error(interrupt_exception + e.getMessage());
}
// to do to send each time, should have some sleep code
if (AugmedixConstants.WEBAPP_URL.equals(AugmedixConstants.EMPTY_STRING)||!StatsNetworkChecker.checkIsConnected(con)) {
Utility.populateNetworkStat();
mLogger.error(may_be_provider_not_login_yet);
} else
sendUXMetrics();
} while (running);
if (!uxMetricsQueue.isEmpty()) sendUXMetrics();
}
});
threadToSendUXMetrics.start();
}
If You are using only one thread in the network, then usage of the thread.sleep() is fine. If there are multiple threads in synchronization, then the thread.sleep() command will block all the other threads that are currently running.
As per the details you've provided, there is only one thread present which isn't blocking any other active threads which are running in synchronization, so using thread.sleep() shouldn't be a problem.
Use Handler.postDelayed to schedule tasks if you are working in UI Thread and Thread.sleep if you are working in background thread.
Apparently you are sending some data using network, you must do it in the background thread, hence Thread.sleep is recommended.
Simple is:
Thread.sleep(millisSeconds): With this method, you only can call in background tasks, for example in AsyncTask::doInBackground(), you can call to delay actions after that. RECOMMENDED CALL THIS METHOD IN BACKGROUND THREAD.
Handler().postDelayed({METHOD}, millisSeconds): With this instance, METHOD will trigged after millisSeconds declared.
But, to easy handle life cycle of Handler(), you need to declare a Handler() instance, with a Runnable instance. For example, when your Activity has paused or you just no need call that method again, you can remove callback from Handler(). Below is example:
public class MainActivity extends Activity {
private Handler mHandler = Handler();
public void onStart(...) {
super.onStart(...)
this.mHandler.postDelayed(this.foo, 1000)
}
public void onPaused(...) {
this.mHandler.removeCallback(this.foo)
super.onPaused(...)
}
private Runnable foo = new Runnable() {
#Override
public void run() {
// your code will call after 1 second when activity start
// end remove callback when activity paused
// continue call...
mHandler.postDelayed(foo, 1000)
}
}
}
The code above just for reference, I type by hand because don't have IDE to write then copy paste.

Serialized incoming aidl calls in one Thread

I have an App (Client) that performs remote calls using AIDL to a second App (Server). Each call to through the Binder is executed in the Server app in a different thread (TID) as designed by AIDL solution.
Is it possible to make all calls executed in the Server app be executed in just one thread? We have control over all callers (Client apps) and they will perform call in a serial mode and we don't need Server app perform the calls in a multithread way.
So, if the Client App 1 performs a remote call to a method that takes 30 seconds and before it, a second Client App 2 performs a call to the same method (or even other method) we want this second call be executed in the same Thread of the first call.
Messenger is not an option for now.
=== Updated ====
Message is not an option (for now). Here more details: We have a service with 2 type of binders: a) TransacionManager (tm) and DAOImpl (dao).
We first do a call to tm.begin() in the client and even its processed synchronously, on the Service side its is executed in a thread from Thread Pool (android aidl code). This thread TID #1 performs the begin transaction command in SQLite database.
Then we do a call to dao.selectNextId() - synchronously - and in the Service it is executed in the TID #2. In the selectNextId() method we check if the database is inTransaction and it returns false.
To confirm that the threads was the problem, we put everything in a single call to another binder (allDAO). So when we call allDAO.do() it runs on the Service side in another thread TID #3 and performs begin transc and insert very well.
Not sure if the problem is SQLite that manage different threads as separated requests (how to deal with)... We just want the Service (using aidl) perform every call from any clients in a same single thread everytime.
I was working with Mario on this issue and using the #pskink's code snippet we solved the multithreading issue.
The issue was solved redirecting all aidl calls to the main thread. To do this, we used a Handler thats receives the MainLooper and a Runnable that extends CountDownLatch.
The code of our solution bellow:
// SyncHandler.class
public class SyncHandler {
private SyncRunnable mRunnable;
public SyncHandler() {
super();
}
public SyncHandler start(#NonNull SyncRunnable runnable) {
mRunnable = runnable;
final Looper looper = Looper.getMainLooper();
Handler handler = new Handler(looper);
handler.post(mRunnable);
try {
mRunnable.await();
} catch (InterruptedException e) {
Log.e(this, "Error when SyncHandler was awaiting.", e);
}
return this;
}
public static class ReturnValue<T> {
public T value;
}
}
// SyncRunnable.class
public final class SyncRunnable extends CountDownLatch implements Runnable {
private Runnable mRunnable;
public static SyncRunnable create(Runnable runnable) {
return new SyncRunnable(runnable);
}
private SyncRunnable(Runnable runnable) {
super(1);
mRunnable = runnable;
}
#Override
public void run() {
Log.d(this, "SyncRunnable.run() executed on thread: " + Thread.currentThread());
mRunnable.run();
countDown();
}
}
//And the database call:
// TransactionManager.class
public synchronized void begin(final int ownerHashCode, String ownerName) throws RemoteException {
SyncHandler handler = new SyncHandler().start(SyncRunnable.create(new Runnable() {
#Override
public void run() {
if (mOwner == null) {
mOwner = ownerHashCode;
for (Database database : mDatabases) {
database.beginTransaction();
}
} else if (mOwner == ownerHashCode) {
throw new DbTransactionException("Error: TransactionOwner == owner");
}
}
}));
}
// DaoHelper.class
public synchronized long insert(Dao dao) {
final SyncHandler.ReturnValue<Long> value = new SyncHandler.ReturnValue<>();
SyncHandler handler = new SyncHandler().start(SyncRunnable.create(new Runnable() {
#Override
public void run() {
Log.d(DaoHelper.this, "db.inTransaction: " + mManagerDb.getDatabase().inTransaction());
value.value = mManagerDb.getDatabase().insert(mTable, null, mContentValues);
}
}));
return value.value;
}

Why does runOnUiThread() not work inside Service?

I am creating an application that needs to update values every minute even if the app isn't running.
Of course, I have set up a simple Service to do that. I have debug messages set up to tell me when the Service starts, when it updates (every minute), and when it closes. I also have a message telling me when the values update inside a runOnUiThread() method. All of my messages activate except for the one in the runOnUiThread(). Is there something I'm doing wrong (of course there is)? What do I need to change?
Code:
#Override
public void handleMessage(Message message) {
try {
if (!serviceStarted) {
serviceStarted = true;
serviceTest = true;
while (serviceStarted) {
new MainActivity().runOnUiThread(new Runnable() {
public void run() {
OverviewFragment.refresh(getApplicationContext());
System.out.println("yay");
}
});
Thread.sleep(((1 /* minutes */) * 60 * 1000));
System.out.println("Updated values through service.");
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
stopSelf(message.arg1);
}
So there's no need to do that, unless you're creating a Thread inside
of it
Gabe Sechan's answer is correct.
But if you are using a separate thread then instead of following code:
new MainActivity().runOnUiThread(new Runnable() {
public void run() {
OverviewFragment.refresh(getApplicationContext());
System.out.println("yay");
}
});
Try, this code:
new Handler(Looper.getMainLooper()).post(new Runnable() {
public void run() {
OverviewFragment.refresh(getApplicationContext());
System.out.println("yay");
}
});
As per Android docs
Caution: A service runs in the main thread of its hosting process—the
service does not create its own thread and does not run in a separate
process (unless you specify otherwise).
You can't create an Activity by calling new. It doesn't initialize properly that way.
Also, Services by default run on the UI thread. So there's no need to do that, unless you're creating a Thread inside of it. If you are- runOnUIThread is just syntactic sugar for posting a runnable to a handler. So you can just do that instead.
Try using a handler or LocalBroadcastManager to send a message to the activity.
See this question: Accessing UI thread handler from a service
You can use Looper.getMainLooper() within a Handler to post a Runnable that executes whatever you're trying to execute.
A good alternative though, like jinghong mentioned, is to use broadcasts - in other words, use a different pattern.

Android: Create a background thread that runs periodically and does UI tasks?

OK, so I know how to do a backround task, I know how to do a periodic task (using handle postdelayed and runnable), I also know how to do UI task from background thread (via handler) but I am not able to execute a periodic background task that does some action on the UI thread.
I am trying to execute some background task every minute in which I have to make a network call. After the call is over, depending on the output I have to update the UI. I tried to do something like this
private void DoTask() {
Thread thread = new Thread() {
public void run() {
Looper.prepare();
final Handler handler = new Handler();
handler.post(netRunnable);
Looper.loop();
}
};
thread.start();
}
Runnable netRunnable = new Runnable() {
#Override
public void run() {
handler.getLooper().prepare();
final Handler handler1 = new Handler(Looper.getMainLooper());
if ( do background work and check result){
handler1.post(new Runnable() {
#Override
public void run() {
//Do UI Task
}
});
}
handler.getLooper().loop();
handler.postDelayed(netRunnable, 60000);
}
}
I understand that there might be some fundamental flaws with my implementation but I do not know how to do this task properly. Right now it is giving the error that Only one Looper may be created per thread.I get what it is trying to say. But can anyone please suggest to do this the right way.
You could use Async Tasks. These are designed for it :
http://developer.android.com/reference/android/os/AsyncTask.html
It allows you to execute a network call in the background, then when you get the result, execute an action on the UI thread
Declaration :
private class MyTask extends AsyncTask<Input, Void, Output> {
protected Output doInBackground(Input... inputs) {
// do something on the network
return myOutput;// use this to transmit your result
}
protected void onPostExecute(Output result) {
// do something on UI thread with the result
}
}
If you want to repeat it, just create a runnable to launch it, and after every call, schedule the next one :
MyTask myTask;
Handler handler = new Handler();
Runnable myRunnable = new Runnable() {
#Override
public void run() {
MyTask myTask = new MyTask();
myTask.execute(myArg);
handler.postDelayed(netRunnable, 60000); // schedule next call
}
}
To launch it for the first time :
handler.postDelayed(myRunnable, 60000);
Or, if you want to launch it immediately :
handler.post(myRunnable);
Do not forget to cancel the Task when your activity is destroyed :
myTask.cancel(true);
Maybe you are better of, creating a seperate (Intent)Service and calling it periodically with postDelayed. Create a BroadcastReceiver in your Activity and handle UI changes there.
Another hint for handling UI changes from other threads: It is not possible. Therefore you need to call runOnUiThread. Here is how to use it
If activities are frequently switching, why not reversing the responsibilities. You might create a service which executes a periodic network task.
Then,
- either your activities periodically call this service to get the value.
- or you use a listener system : you create an interface that your activities must implement in order to get notified from the task completion

Check Database at every seconds

In My application I want to check data after every second, using service.
I have tried to use Timer but it doesn't allow me to use 'runOnUiThread' in service.
In Activity Timer works fine.
or
Is there any other way to trace database at every seconds?
Implement a Runnable, that way you can use the runOnUiThread(runnable) functionality.
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
//do ui update
}
};
Edit: try this: More efficient way of updating UI from Service than intents?
Edit2: http://developer.android.com/resources/articles/timed-ui-updates.html
Use thread u can trace the data base every time
try{
thread=new Thread()
{
#Override
public void run() {
while(set) {
thread_Run();
}
}
};
}
catch(Exception e)
{
Toast.makeText(this, "error", Toast.LENGTH_SHORT).show();
}

Categories

Resources