I'm trying to use SocketIO in my Android app to communicate with the server.
Here's my code:
socket = IO.socket("server-address");
socket.connect();
socket.on("init", new Emitter.Listener()
{
#Override
public void call(Object... args)
{
handleResult(args[0].toString());
}
});
I'm unable to update the UI from the call function since it is running in the same thread as the UI (my understanding of the issue).
I've tried using an AsyncTask as well but it moves onto doInBackground before the "call" has completed.
How do I update the UI from within this call function? Or how do I send some data out of it?
You cannot change UI elements from a non-UI thread. Use runOnUiThread to Update UI.
runOnUiThread(new Runnable(){
#Override
public void run(){
// Updat UI here
}
});
Another way to update UI is to Use Handler.
private void updateUI(final String stringData) {
new Handler().post(new Runnable() {
#Override
public void run() {
// Updat UI here
}
});
}
Related
Why does this code block the main UI in the while loop?
new Thread(new Runnable() {
public void run() {
someButton.post(new Runnable() {
public void run() {
while (HintergrundDienst.laeuft)
{
//some delay code, like Thread.sleep
}
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
//do on ui after HintergrundDienst.laeuft = false
}
});
}
});
}
}).start();
Running this blocks the main ui.
Why does this code block the main UI in the while loop?
Because it is running on the main application thread. Your loop is in a Runnable that you are providing to post(). The documentation for post() indicates that "The runnable will be run on the user interface thread". Here, "the user interface thread" refers to the the main application thread.
I get some error. I really couldn't solve it today :( I get error after set ID data to lblID in FillData() method. It sets ID data properly but lblTitle and lblPrice always returns error like "Only the original thread that created a view hierarchy can touch its views" and program stops running.
Note : This is not my original code. I just minimized it to be more understandable and of course it gives same error like below code. Anyway in FillData() method i get data from wcf service and it returns data properly. i tried runonuithread but it didn't make any sense. Also if i write the code outside of the thread it doesn't fill the controls. Because it's originally gets the data from wcf service.
public class MainActivity extends AppCompatActivity {
LinearLayout lytData;
TextView lblTitle, lblID, lblPrice;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lytData = (TextView)findViewById(R.id.lytNewData);
lblID = (TextView)findViewById(R.id.lblID);
lblTitle = (TextView)findViewById(R.id.lblTitle);
lblPrice = (TextView)findViewById(R.id.lblPrice);
new Thread() {
public void run() {
FillData();
}
}.start();
lytData.setOnTouchListener(new OnCustomTouchListener (context) {
#Override
public void ToLeft() {
new Thread() {
public void run() {
FillData();
}
}.start();
}
#Override
public void ToRight() {
new Thread() {
public void run() {
FillData();
}
}.start();
}
});
}
void FillData() {
lblID.setText("aaa");
lblTitle.setText("aaa");
lblPrice.setText("aaa");
}
The problem is you're trying to update the UI in another thread, but the UI can only be updated in the UI thread. If you're simply updated the UI as your code is showing then you should remove the calls from FillData from the secondary thread, use a secondary thread if you're doing heavy loading inside FillData() otherwise you're better off updating the UI directly in the UI thread:
So instead of doing this:
new Thread() {
public void run() {
FillData();
pd.cancel();
}
}.start();
Just simply call FillData(); outside the new thread.
You can also call runOnUiThread to bring the update to the ui thread:
getActivity().runOnUiThread(new Runnable() {
public void run() {
FillData();
}
});
If your code inside FillData is mixed with heavy load code, then you can bring the runOnUiThread method to inside the FillData and move only the UI update code to runOnUiThread.
If you still want to keep your code the way it is you can "post" changes from your secondary thread like this:
viewElement.post(new Runnable() {
public void run() {
//update UI
}
});
}
viewElement is any UI element that extends from View.
I've been trying to connect to a server to retrieve some data. First thing came to my mind was to create a thread to connect asynchronously.
new Thread(new Runnable() {
#Override
public void run() {
// retrieve data
}
}).run();
But the weird thing is that the thread I created worked synchronous with UI thread and I got a network exception so I ended up using AsyncTask. Do you guys know what could cause a thread to work non asynchronously with the UI thread? My class extends to a fragment.
Your must start your thread with start() and not run() in order to start the new thread:
new Thread(new Runnable() {
#Override
public void run() {
// retrieve data
}
}).start();
How can I make this happend?
Thread t = new Thread(new Runnable() {
#Override
public void run() {
FacebookConnectTask task =
new FacebookConnectTask("facebookId", "token", "email", facebookGender,0, 0);
task.setOnPreExecuteListener(this);
task.setOnDoneListener(this);
task.execute();
}
});
t.start();
public void onPreExecute() {
progressbar.setVisibility(View.VISIBLE);
}
public void onDone() {
progressbar.setVisibility(View.GONE);
}
Since I am opening a new thread, I can not change a UI element in it, so, How can I manage to do something to the UI, when the task starts and when it's finished?
You could do the work in an AyncTask. The AsyncTask executes everything in doInBackground() inside of another thread, which does not have access to the GUI where your views are.
preExecute() and postExecute() offer you access to GUI before and after the heavy lifting occurs in this new thread, you can even pass the result of the long operation to postExecute() to then show any results of processing.
More here: http://developer.android.com/reference/android/os/AsyncTask.html
Example here: http://www.vogella.com/articles/AndroidPerformance/article.html
inside your activity
private Handler myHandler=new Handler();
next in your on done callback
public void onDone() {
myHandler.post(new Runnable(){
#Override
public void run() {
progressbar.setVisibility(View.GONE)
}
})
}
But as already was said. AsyncTask is more siutable for it
I am new to Android, but I ran into this problem...
I need an infinite loop to run some process in the background,
while another infinite loop to accept some socket connection,
and then when a button clicked, I need to make a socket connection to some server.
Almost all the example and tutorial I can find are showing how to create one single thread.
I have try to use runnable (this seems to run at foreground?)
Runnable r=new Runnable() {
public void run() {
while(true){}
}
}; r.run();
and I have tried to use AsyncTask (this run at background, but only one AsyncTask per activity?)
private class Run extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
}
}
but whatever I do, my program only execute the first thread.
My question would be, is it possible to have multi-thread running multi-infinite loop within one activity? If is, how?
Yes, you can create multiple threads.
You can implement the Runnable interface.
new Thread(new Runnable() {
public void run() {
while (true) {
//code something u want to do & it will run infinitely.
//Remove the infinite loop for running finite set of operations.
Log.i("Thread", "Running parallely");
}
}
}).start();
Also, please note that the above thread run indefinitely. If you want to do any finite operations, just put the code inside the run method.
To create a thread that listen for network Connection
new Thread(new Runnable() {
public void run()
{
ServerSocket s = new ServerSocket(PORT_NUMBER);
while(true)
{
Socket c = s.accept();
// read the socket
BufferedReader in = new BufferedReader(new InputStreamReader(c.getInputStream()));
in.read();
}
c.close(); //close the socket
}
}).strat();
Sometimes you want to call up the UI thread from the background thread. You can do that like this:
Thread t = new Thread(new Runnable() {
public void run() {
//Do your background thing here
getActivity().runOnUiThread(new Runnable() {
public void run() {
//Update your GUI here
}
});
t.start();
And getActivity looks like this:
public class YourClass extends AppCompatActivity{
private Activity getActivity(){
return this;
}
//Rest of class here
}