right now i'm doing
public void someStuff(){
new Thread(new Runnable() {
#Override
public void run() {
//doing long task
doOtherStuff();
}
}).start();
}
public void doOtherStuff(){
doEvenMoreStuff();
}
but the problem is that it executes doOtherStuff in the same thread and It needs to be executed in the UI Thread. how can I accomplish this?
I am only using the thread because otherwise the app freezes. I just need doOtherStuff to wait for the thread to finish.
Try this:
this.runOnUiThread(new Runnable() {
#Override
public void run() {
//do something
}
});
this is your activity.
Use handler :
public void doOtherStuff(){
new Handler(context.getMainLooper()).post(new Runnable() {
#Override
public void run() {
// Executes on UI thread
doEvenMoreStuff();
}
});
}
where context might be your Activity
Not sure if best practice but you can Try this:
public void someStuff(){
new Thread(new Runnable() {
#Override
public void run() {
YourActivityClassName.this.runOnUiThread(new Runnable() {
#Override
public void run() {
//doing long task
doOtherStuff();
}
});
}
}).start();
An alternative way of using Handler which other answers suggested is AsyncTask:
It has two methods which can be useful in your case:
doInBackground: which runs in the background thread so your UI won't freeze
onPostExecute: which runs on UI thread after doInBackground finishes. A generic class may look like:
private class MyTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... input) {
//do background processes on input and send response to onPostExecute
return response;
}
#Override
protected void onPostExecute(String result) {
//update UIs based on the result from doInBackground
}
}
and you can execute the task by:
new MyTask(inputs).execute()
Related
I am running a recursive handler which runs some code. I am posting the handler using a HandlerThread. I want to run the next recursive call only after the completion of the previous call.
Is it possible to do so? If not what are the alternatives.
HandlerThread ht = new HandlerThread();
ht.start();
Handler h = new Handler(ht.getLooper());
h.post(new Runnable() {
#override
public void run(){
//Some code
h.postDelay(this,1000);
}
});
Your code should work, but if you want a complete example how to run something recursively using HandlerThread, here it is:
public class Main2Activity extends AppCompatActivity {
private MyWorkerThread mWorkerThread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
mWorkerThread = new MyWorkerThread("myWorkerThread");
final Runnable task = new Runnable() {
#Override
public void run() {
Log.d("TAG", "Done.");
mWorkerThread.postTask(this);
}
};
mWorkerThread.start();
mWorkerThread.prepareHandler();
mWorkerThread.postTask(task);
}
#Override
protected void onDestroy() {
mWorkerThread.quit();
super.onDestroy();
}
}
class MyWorkerThread extends HandlerThread {
private Handler mWorkerHandler;
public MyWorkerThread(String name) {
super(name);
}
public void postTask(Runnable task){
mWorkerHandler.postDelayed(task, 1000); // set timeout which needed
}
public void prepareHandler(){
mWorkerHandler = new Handler(getLooper());
}
}
Don't forget to call handlerThread.quit() in onDestroy
I have to update the list after optimizing the running apps ....
m_optimizeBtn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
launchProgressRing(OptimizationActivity.this);
listAdaptor.notifyDataSetChanged();
}
});
}
Killing the running process in a seprate thread....
public void launchProgressRing(Context ctx){
final ProgressDialog opt_proDialog=new ProgressDialog(ctx);
opt_proDialog.setTitle("Please wait...");
opt_proDialog.setMessage("Optimizing power draining apps...");
opt_proDialog.setIndeterminate(true);
opt_proDialog.show();
opt_proDialog.setCancelable(false);
new Thread(new Runnable()
{
#Override
public void run()
{
//TODO: optimize apps
m_cPowerDrainingApps.killBgRunningProcesses(runningAppsList);
try
{
Thread.sleep(1500);
} catch (InterruptedException e)
{
e.printStackTrace();
}
runOnUiThread(new Runnable()
{
#Override
public void run()
{
opt_proDialog.dismiss();
}
});
}
}).start();
}
listAdaptor.notifyDataSetChanged() is not working ,don't know why ???
What I suggest is to use AsyncTask to do the job. AsyncTask has two good methods for you:
doInBackground: which you can put most of the background tasks in there
onPostExecute : which you can put the logic of what needs to be done when the background task has finished its job.
So your code should look like this:
public class BackgroundTask extends AsyncTask<Void,Void,Void>{
private ListAdapter mAdapter;
public BackgroundTask(ListAdapter adapter)
{
mAdapter = adapter
}
public Void doInBackground (Void... params)
{
//define m_cPowerDrainingApps somewhere
m_cPowerDrainingApps.killBgRunningProcesses(runningAppsList);
try
{
Thread.sleep(1500);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
public Void onPostExecute (Void... params)
{
//do your UI things
mAdapter.notifyDataSetChanged();
}
}
and then run this with:
new BackgroundTask(listAdapter).execute()
Use a Handler and its postDelayed method to invalidate the list's adapter as follows:
final Handler handler = new Handler()
handler.postDelayed( new Runnable() {
#Override
public void run() {
adapter.notifyDataSetChanged();
handler.postDelayed( this, 60 * 1000 );
}
}, 60 * 1000 );
You must only update UI in the main (UI) thread.
I'm new to android and have been doing some reading about worker threads and not blocking the UI thread. I'm playing around with a simple timer app that starts a thread that updates a textview every second when the activity is created. So my question is, these days what is the best way to do this. Both of the two examples below work but is there a better (more efficient/ more Android) way?
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
seconds++;
runOnUiThread(new Runnable() {
#Override
public void run() {
secondsTextView.setText(seconds);
}
});
handler.postDelayed(this, 1000);
}
}, 1000);
or
new Thread(){
#Override
public void run(){
try{
while(!isInterrupted()){
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
seconds++;
secondsTextView.setText(seconds);
}
});
}
}catch(Exception e){
Log.e("Activity1", e.toString());
}
}
}.start();
The more efficient way is:
timeOnTextView.postDelayed(new Runnable() {
#Override
public void run() {
seconds++;
timeOnTextView.postDelayed(this, 1000);
}
}, 1000);
The run() of the Runnable passed to postDelayed() is invoked on the main application thread, so you do not need to use runOnUiThread().
Since postDelayed() is implemented on View, you do not need a Handler.
I have tried to implement object in Android that would work in its own thread (I do not want to make handler public, I want to wrap sentMessage method with own public api). It has public methods to pass data to object. This object is associated with activity lifecycle (onResume, onPause). I would like to use looper and handler, not just pure Java thread with infinite loop. I want to start worker thread on resume and stop working on pause callback. Object has to wait for new message infinitely.
This is my code below:
public class ThreadingObject {
private MyThread thread;
public ThreadingObject() {}
public void onResume() {
thread = new MyThread();
thread.startWorking();
}
public void onPause() {
thread.stopWorking();
}
public void setMessage(Object object) {
Message msg = new Message();
msg.obj = object;
thread.handler.sendMessage(msg);
}
protected void work(Object object) {
//Do something with object in own thread
}
private class MyThread extends Thread {
public Handler handler;
#Override
public void run() {
Looper.prepare();
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
ThreadingObject.this.work((String[]) msg.obj);
}
};
Looper.loop();
}
public void startWorking() {
start();
}
public void stopWorking() {
handler.getLooper().quit();
}
}
}
Is it correct implementation? I receive warning: "sending message to a handler on a dead thread". Is there any issue that I do not see?
It is my implementation:
public class ThreadingObject {
private HandlerThread thread;
private Handler handler;
private Handler.Callback handlerCallback = new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
work(msg.obj);
return true;
}
};
public ThreadingObject() {}
public void onResume() {
thread = new HandlerThread("SurfaceView HandlerThread");
thread.start();
handler = new Handler(thread.getLooper(), handlerCallback);
}
public void onPause() {
if(thread != null) {
thread.quit();
thread = null;
}
handler = null;
}
public void setMessage(Object object) {
Message msg = new Message();
msg.obj = object;
handler.sendMessage(msg);
}
protected void work(Object obj) {
//Working
}
}
In that run() method, if you need to re run or use loop, you need to add it by your self, ex.
and your error, is happen because you try to call the thread that already finish.
boolean aLoopLoopLoop = true;
Handler handler;
// this handler, you no need to declare it repeatedly, just declare it in onCreate() is enough
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
ThreadingObject.this.work((String[]) msg.obj);
}
};
// -----
#Override
public void run() {
Looper.prepare();
final Looper looper = Looper.myLooper();
while(aLoopLoopLoop) {
// write your code here
Looper.loop();
}
// after loop exit, quit loop
handler.postDelayed(new Runnable() {
#Override
public void run() {
looper.quit();
}
}, 3000);
}
// -----
public void stopWorking() {
aLoopLoopLoop = false;
}
I want to update the UI during an intensive task. I've got a separate thread where the intensive method runs but I can't update the UI...
This is the structure of my code:
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
updateUI();
Thread t = new Thread(){
#Override
public void run(){
runIntensiveMethod();
}
}
t.start();
}
});
If I comment runIntensiveMethod(); the animation runs perfectly fine. However, it seems as though the UI queue is delayed until the method is run.
How can I post an animation and run the method while the animation runs?
Everything I've tried halts the UI until the method has been executed.
You should set a priority for that thread:
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
Also check here
Just call runOnUiThread when you want to refresh from your runIntensiveMethod()
runOnUiThread(new Runnable()
{
#Override
public void run()
{
updateUI();
}
});
Change your code to this, this should work.
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Thread t = new Thread(){
#Override
public void run(){
runIntensiveMethod();
runOnUiThread(new Runnable() {
public void run() {
updateUI();
}
}
}
t.start();
}
});