I have created an Android App that handles a TCP Client connection with an AsyncTask. Server-Client interaction works perfectly. Now, I have a question about the implementation I have made to pass a String from the Client Thread to the Main Thread:
I want to set the received String from the Client Thread to a TextView, and non-main threads cannot interact with the App UI on Android.
So what I did was to create a temporary thread on the Main one that checks every 100ms if the data has been received on the Client thread, and then use it.
Here are the simplified pieces of code:
Client Thread (No access to UI)
private volatile boolean hasReceivedData;
private String receivedData;
...
receivedData = inBuffer.readLine();
hasReceivedData = true;
...
public String getReceivedData() {
return receivedData;
}
Main App Thread (Access to UI)
private ClientThread client;
private TextView textView;
private Thread dataChecker;
...
dataChecker = new Thread(new Runnable() {
#Override
public void run() {
while (!client.hasReceivedData()) {
Utils.sleep(100);
}
textView.setText(client.getReceivedData());
}
});
dataChecker.start();
I would like to know if there is a better/correct way to achieve this or a simpler one.
Thanks in advance!
Your AsyncTask has onPostExecute() method, which runs after doInBackground() thread is completed. Use that to update the UI.
Related
I have a code that worked very good. But when i run several it, my app crashes for this error:
03-24 14:47:34.542 3489-3546/com.example.com E/AndroidRuntime﹕ FATAL EXCEPTION: pool-4-thread-1
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
My code:
public class Sample {
public Sample(Context context) {//error for this line
mContext = context.getApplicationContext();}
public void doSignUp( String firstName, String lastName, String userName) {
//some code for signup users
}
}
public class Service {
Runnable task = new Runnable() {
#Override
public void run() {
Sample sample = new Sample(getApplicationContext());
Sample.doSignUp(firstName,lastName,userName);
decreaseCounter();
if(getCounter() <= 0){
stopSelf();
}
}
};
Your problem is that you are probabley trying to update a UI componenet from a background thread (That is-a thread that does not run on the main thread - or "The UI thread" asyou will probabley read on other places), in order to achieve that you should pass a "Handler" that was created on either activity or a fragment (or something else that got created on the Main\UI thread) since the handler is connected to WHERE IT WAS CREATED it will act as a "bridge" between the two thread.
The error you are getting is from the OS, That Looper object is the one responsible to "push" tasks to the main\ui thread task queue.
You can also use asynctask that will essentially do the above for you.
I have a code in the UI Thread that call to another Thread. This new Thread wait for a server response to execute an database update.
When the new Thread send the post content the server send the answer fine, but the update process to the database stops when the screen (activity) load the next item to calculate and send it to the server again.
My code looks like this
public class MyActivity extends Activity {
onCreate(){ ... }
public void pushButton(View v) {
...
//Call the Thread
MyOwnThread t = new MyOwnThread(arg1, arg2);
t.start();
showTheNextItemToProcess();
}
}
MyOwnThread looks like this
public class MyOwnThread extends Thread {
public MyOwnThread(String arg1, Object arg2) { ... }
public void run() {
if(arg1.equals("ok_status") {
//The code on this part stops wen the UI Thread show the next item to process
for( ... ) {
// ...
}
}
}
}
I tried with send a clone of the variables inside the new Thread constructor, but the result it's the same. I don´t know why the UI Thread interrupts the another Thread. With the ListenableFuture (Google Guava) it´s the same.
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1));
ListenableFuture<String> futureTask = service.submit(new Callable<String>(){
public String call() {
//Send the post to the server
}
});
Futures.addCallback(futureTask, new FutureCallback<String>() {
#Override
public void onSuccess(String arg0) {
//when get the answer from the server, executes the db update
//the UI thread stop this too
}
});
I don't see errors in the LogCat. Your help is welcome, sorry for my bad english.
Thanks!
EDIT
I changed my code to use full threads (extends Thread), with WIFI connection the app sends the package to the server and the server returns the response, the app takes the value sended from the server and trigger the db update, it's fine!. But with the movil data (local operator), the app calls and runs the Thread but the thread simply not continue running. I had set the priority to MAX and it's the same. Anyone know why????
Thanks!
I do some network request simultaneously and get the response using HTTPClient in Android. I am using threadsafeclientconnmanager in order to have thread safe connection.
In order to do it simultaneously I am using Java ThreadPool.
private enum STATE { state1, state2, state3 };
ExecutorService executor = Executors.newFixedThreadPool(nThreads);
and submit 3 runnable:
executor.submit(new Processor(state1));
executor.submit(new Processor(state2));
executor.submit(new Processor(state3));
And this Processor class which extends runnable:
class Processor implements Runnable {
private STATE state;
public Processor(STATE state) {
this.state = state;
}
#Override
public void run() {
switch (state) {
case state1:
// Do something
// Call Back to update UI
break;
case state2:
// Do something
// Call Back to update UI
break;
case state3:
// Do something
// Call Back to update UI
break;
}
latch.countDown();
}
}
As you see in the run method, for every state, I do some instruction and then I need to update UI using callBack methods.
And since that is UI thread every callback method should be :
runOnUiThread(new Runnable() {
#Override
public void run() {
//Update UI
}
});
Is there any better solution to update UI when we are having Java thread pool in Android?
You should exec the network connection in other thread, never in main UI thread. When you will have new data, you send it from network thread to main thread.
You can use AsyncTask or Handler.
http://developer.android.com/reference/android/os/AsyncTask.html
https://developer.android.com/training/multiple-threads/communicate-ui.html
Asynctask has "updatePublish" to send data to UI Thread.
Handler is a message system to send data to UI Thread and vice versa
I think that Handler is the better option for you.
I would like to have an application which either loads or saves data through a HTTP request, however the data must interact with the UI thread. Ideally, I would like a single thread to use an IF statement on a message to determine if the request is to "load" or "save".
What would be the simplest way of doing this with the smallest amount of code?
Also, do instances of Handlers run on individual threads?
EDIT: This is the code I am using now:
Handler doStuff = new Handler(){
#Override
public void handleMessage(Message msg){
if(msg.what == 1){
// Load all the information.
// Get the ID from sharedPrefs
SharedPreferences details= getSharedPreferences("details", 0);
String ID = patDetails.getString("id", "error");
// Load up the ID from HTTP
String patInfo = httpInc.getURLContent("info.php?no="+AES.encrypt("387gk3hjbo8sgslksjho87s", ID));
// Separate all the details
patientInfo = patInfo.split("~");
}
if(msg.what == 2){
// Save the data
}
}
};
Eclipse halts the debugging and displays, "Source not found" for StrictMode.class
I suppose it's because it's using the Main thread to access the internet although it's running in individual threads.
Any idea.
Handlers do run on individual threads. Check that link. You should also check out AsyncTask.
I would propose submitting the jobs as Runnable to a single-threaded ExecutorService:
public class SomeClass {
private ExecutorService execService = Executors.newSingleThreadExecutor();
public void doSomething() {
final String someUiData = // retrieve data from UI
execService.submit(new Runnable() {
#Override
public void run() {
// so something time-consuming, which will be executed asynchronously from the UI thread
// you can also access someUiData here...
}
});
}
}
This way, the UI thread will not block whereas you can easily submit a different Runnable for different operations and the ExecutorService will completely take care of keeping it async.
Edit: If you need to interact with the UI, do so before becoming asynchronous and keep the result in final variables.
I have an Android service which spawns a thread.This thread waits for network data and after receiving that data I want to show Ok Cancel Dialogbox.
I was getting exception can't create handle that should have Looper.prepare().I added Looper.prepare() and Looper.loop() then now I am not getting any exception but its waiting infinitely.
Instead of using a sole thread it's better to use an AsyncTask which is also a speacialized thread for Android.
You can wait for data in the AsyncTask's doInBackGround method and when you received data you can call publishProgress() which will invoke onProgressUpdate method of AsyncTask.
At onProgressUpdate you can update the UI without blocking the main thread and also this is the preferred way of doing long time operations in background like network listening etc.
Check AsyncTask for more info and how to use it.
http://developer.android.com/reference/android/os/AsyncTask.html
You can invoke the UI thread(showing alert dialog) in non-UI thread by using handlers as like below code
new Thread(new Runnable()
{ public void run()
{
try {
///do your stuff in
mHandlerShowDialog.post(mUpdateShowDialog);
///do your struff
}
} ).start();
final Handler mHandlerShowDialog= new Handler();
final Runnable mUpdateShowDialog = new Runnable() {
public void run() {
// show your dialog here
}
};