I have a Thread with open socket connection in a activity, I like to use the thread globaly so that I can get data from thread in other Activities. Somethink like running on the background...
Does anyone have a solution or examples for me?
Thank u.
You are looking for Service
or try this code
void runInBackground() {
new Thread(new Runnable() {
#Override
public void run() {
// DO your work here
// get the data
if (activity_is_not_in_background) {
runOnUiThread(new Runnable() {
#Override
public void run() {
//uddate UI
}
});
}
runInBackground();
}
});
}
And the third method using Async Task-- Understanding AsyncTask
If you want multiple activities to have access to this thread then I would combine Vaibs_cool's sample of running a thread (it's just a normal Thread, nothing Android specific about it) and then...
extend Application (make an entry for it in the Manifest) and put that Thread in there.
That way all your activities can talk to it.
You have two options:
Service
AsyncTask
If you want to open socket and make it opened even after Activity close use Service
On other hand if you want to open socket during Activity is running and close on Activity close then use AsyncTask
You can find example how to use AsyncTask here
From Docs:
Network operations can involve unpredictable delays. To prevent this from causing a poor user experience, always perform network operations on a separate thread from the UI. The AsyncTask class provides one of the simplest ways to fire off a new task from the UI thread.
Related
I've created a nested class within my Activity
public class MissionsActivity extends Activity {
class UpdateMissions implements Runnable {
#Override
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
[...]
}
[...]
}
In the thread I have to read a file and update some TextFields in the layout. I've tried implementing the run() method with a while(true) that reads and updates the fields, but the app just crashes when I start that Activity.
UPDATE: I've called the execute() method inside the onCreate() method of the UI Activity. The Task is only working the first time I enter the Activity, if i change and go back it won't do anything.
Hey a solution could be trying to use Java's Executor Framework. Put the following code in your Activity.
With executors, you can use a cachedThreadPool() singleThreadExecutor() fixedThreadPoolExecutor(int numOfThreads) etc.
Executors.newSingleThreadExecutor().submit(new Runnable() {
#Override
public void run() {
//Your task here.
}
});
Please note there are numerous Threading Models and techniques in Android, some Android Specific, some based in Android.
AsyncTask
HandlerThread
You can use an AsyncTask. It allows you to load the file and show the progress on ui thread until the load it's finished.
Here you have a good example Download a file with Android, and showing the progress in a ProgressDialog
I would recommend using RxJava or Live Data if you are more advance in developing but also the first solution is fine enough for beginning
https://developer.android.com/topic/libraries/architecture/livedata.html
This is not the problem about being able to call a method in the main/UI thread but being able to do so instantaneously.
It is my knowledge that you are not normally allowed to interact with the UI thread directly because of the UI responsive requirements. It would make sense then to have a system in place to queue the requests you have for the main thread and we do have that system with the looper, handler, etc.
Here is what I did:
I did some task in the background thread and I want to intimate the main thread as soon as a condition gets satisfied(I created a listener for it) and I use the response handler to post it..something like this:
if(mNoOfPendingRequests >= mNoOfRequestsConsideredEnough){
mShouldFlagEnoughRequestsAtATime = true;
Log.i("ThumbnailDownloader: ","Enough Requests Queued");
//Now inform about this to PhotoGallery right now
mResponseHandler.postAtFrontOfQueue(new Runnable() {
public void run() {
mEnoughRequestsListener.onEnoughRequestsQueued(mShouldFlagEnoughRequestsAtATime);
}
});
}
else{
mShouldFlagEnoughRequestsAtATime = false;
mEnoughRequestsListener.onEnoughRequestsQueued(mShouldFlagEnoughRequestsAtATime);
}
If I don't inform the PhotoGallery about the enough requests sent already, it would continue to send more and more requests and app becomes unresponsive.
Also, the requests are queued and are executed later resulting in too many requests.
My question is therefore:
Is there a way to call a method/inform in UI thread from a background thread almost instantaneously?
You can run things on UI thread doing this:
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
// put your code here :)
}
});
Is there a way to call a method/inform in UI thread from a background thread almost instantaneously?
Not really. Your postAtFrontOfQueue() is about as close as you can get, and as the boldface note mentions in the docs, "This method is only for use in very special circumstances -- it can easily starve the message queue, cause ordering problems, or have other unexpected side-effects."
If I don't inform the PhotoGallery about the enough requests sent already, it would continue to send more and more requests and app becomes unresponsive. Also, the requests are queued and are executed later resulting in too many requests.
Have more smarts in your queue, to know when to throttle back request processing based upon whatever your "enough" algorithm is.
This method works like a charm unless you already have lots of events in your events queue.
activity.runOnUiThread(new Runnable() {
public void run() {
// call your method here
}
});
Yes, you can call using activity context
runOnUiThread() and pass runnable object and write code inside run() method.
It is not clear from your code, what onEnoughRequestsQueued does. If all it is doing is telling the posting thread that it should stop sending requests, then you can probably accomplish the same thing with a simple volatile boolean
If the thread enqueuing requests stops doing so, when the variable is true, and the background thread sets it true, and the variable is volatile you should be good.
Quick question: I have been using frameworks that spawn worker threads to perform asynchronous tasks, a good example is Retrofit. Within the success/failure sections, I may pop up a Dialog box which would need to be on the UI thread. I have been accessing the underlying
Activity/UI thread in this fashion within the success/failure sections of Retrofit:
Dialog dialog = new Dialog(LoginActivity.this, R.style.ThemeDialogCustom);
This works well 99.9% of the time but every once in a while, I receive the following error when creating a Dialog box:
android.view.WindowManager$BadTokenException
LoginActivity.java line 343 in LoginActivity$6.success()
Unable to add window -- token android.os.BinderProxy#41662138 is not valid;
is your activity running?
So, is my approach the most stable way to access the Activity context/UI thread from a worker thread or do I need a different approach?
If you work with threads and not using Asynctasks, always run everything that changes UI in runOnUIThread like this
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
//change UI
}
});
The more generic way to do it is this, which is pretty much the same
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
//change UI
}
})
See here the minimal difference between runOnUIThread and MainLooper
If you want to check if you are on the main/ui thread
if(Thread.currentThread() == Looper.getMainLooper().getThread()) {
//you are on the main thread
}
AFAIK, there is nothing wrong with the approach you are using. The problem is occurring because the by the time the worker thread finishes and you are trying to show the dialog, the instance of the Activity has finished. So, the crash is totally dependent on the amount of time it takes for the thread to finish. And it seems that in your case, the thread mostly finishes when the Activity is still active; hence you don't get the error is most cases.
What you need to do is to check if the Activity is still running before trying to show the Dialog. One of the simplest ways would be to
if(!((Activity) LoginActivity.this).isFinishing())
{
//safe to show your dialog
}
I'm new to android, I need to start a Thread Multiple times to do a regular work as the listen a thing. But I searched and found that can't do this. So I decided to put
while(true){
listen some thing
do another something depends for listen
}
in the run() method.
But How can I implements this idea? Is it possible ? and How?
You should use Handler.post() whenever you want to do operations in the UI thread.
So let's say in the callback (which is running in separate thread) you want to change a TextView's text, you should use Handler.post(). In Android, as in many other UI frameworks, UI elements (widgets) can be only modified from main thread.
mHandler = new Handler();
new Thread(new Runnable(
#Override
public void run () {
// Perform long-running task here
// (like audio buffering).
// you may want to update some progress
// bar every second, so use handler:
mHandler.post(new Runnable() {
#Override
public void run () {
// make operation on UI - on example
// on progress bar.
}
});
}
)).start();
Of course, if the task you want to perform is really long and there is a risk user might switch to some another app in the meantime, you should consider using Service.
If you start your thread inside a while loop with true condition, it'll kill your device. You'r device will hang. Your code should be event triggered. You can have a Service running in the background to do that and listen for your events.
How do I use a thread to run some code continuously whilst an Apps running, using the information it gives to periodically update the UI of the App.
Specifically the thread would run some code that searches through a text file in order to find co-ordinates which would then be plotted over a PNG on the UI. This would update automatically say every second maybe every half second, and would clear the image then redraw the points.
How do i first of all set up the thread then second of all send information from the thread back to the UI and have it update?
Any example code would be great or any information you've come across that gives example code. I'm not trying to do it the best way at the moment, just trying to hack it together, so if you know easy and quick (but awful) ways of doing this don't feel afraid to share.
This may help u...
//on create
Thread currentThread = new Thread(this);
currentThread.start();
after on create
public void run() {
try {
Thread.sleep(4000);
threadHandler.sendEmptyMessage(0);
} catch (InterruptedException e) {
//don't forget to deal with the Exception !!!!!
}
}
private Handler threadHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
Intent in = new Intent(getApplicationContext(),****.class);
startActivity(in);
}
};
This is a very common scenario and its far boyend the scope of a simple answer to your question.
Here are two usefull links:
http://developer.android.com/guide/components/processes-and-threads.html
http://www.vogella.com/articles/AndroidBackgroundProcessing/article.html
And there are a lot more.
Here are two different approaches for you as starting point:
Update gui from your thread, only needs syncronzation with the UI thread. Pass your Activity into your thread, it provides the method: runOnUiThread
Define an interface to provide callbacks, let the calling ui class (activity) implement your interface and register it as listener to your thread. Then you can call the callback, when ever you want. Don't for to syncronize
Try to use service(or IntentService - http://developer.android.com/guide/components/services.html) for background work and BroadcastReceiver to update the UI thread from the service.
Use the AsyncTask class (instead of Runnable). It has a method called onProgressUpdate which can affect the UI (it's invoked in the UI thread).