Variable not updated within handler.post's run method in Android - android

I created a new thread to handle my TCP management needs. I did this in order to keep the UI thread active while it's doing all sorts of socket magic. The problem I'm having is that the variable num used in ServerThread doesn't seem to updating within the handler.post()'s run method. It changes once but subsequent iterations within my while(true) loop no longer changes its value. However, outside handler.post() I noticed that it is changing properly. I have included a log command for logcat in order to see the values of num so that's why I know this is what is happening. The thing is, I need the variable num inside the run() method to update a few things in the UI thread.
May be there's something wrong with the way I declared num. I did not include in the code most of the things I think is irrelevant to my question, so if I missed something please let me now. This is my first adventure into android java threading so some help would be really appreciated. Just run out of mental energy tonight.
public class MainActivity extends Activity {
private int num = 0;
private Handler handler = new Handler();
//Other declarations
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Do bunch of things including starting ServerThread
//and creating a TCP server socket
}
public class ServerThread implements Runnable{
public void run(){
// ...
// Do bunch of stuff including waiting for a client to connect
try{
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
while(true){
num = in.read();
Log.e("MainActivity", "A:" +num); //<-- WORKS FINE
if(num == -1) //client socket closed
break;
handler.post(new Runnable() {
#Override
public void run() {
Log.e("MainActivity", "B:" +num); //<-- DOES NOT WORK FINE
//Do bunch of stuff here with the variable num
//including updating the UI thread
}
}
}catch(Exception e){
// ...
}
}
}

Related

How to return to main thread Android

I have a simple Activity with two buttons "On" and "Off". I want start changing color of background in cycle with button "On" and stop this with button "Off". Also I need to have red color by click on "Off" button. I have wrote simple programm and everything is fine, but I can't understand one thing. Why the last color not always red? If I use code in main threads cycle
Thread.sleep(100);
or
Thread.sleep(1000);
I always have red color, but if I set
Thread.sleep(10);
I have random last color. Why??
Thank you !!
I have this code:
public class MyActivity extends Activity {
final Handler myHandler = new Handler();
private int randColor;
final Runnable updateColor = new Runnable() {
public void run() {
final Random random = new Random();
randColor = Color.rgb(random.nextInt (255), random.nextInt (255), random.nextInt (255));
mRelativeLayout.setBackgroundColor(randColor);
}
};
private ColorChanger myThread;
class ColorChanger extends Thread {
private volatile boolean mIsStopped = false;
#Override
public void run() {
super.run();
do
{
if (!Thread.interrupted()) {
myHandler.post(updateColor);
}
else
{
return;
}
try{
Thread.sleep(100);
}catch(InterruptedException e){
return;
}
}
while(true);
}
public void stopThis() {
this.interrupt();
}
}
private RelativeLayout mRelativeLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
mRelativeLayout = (RelativeLayout)findViewById(R.id.relativeLayout);
}
public void onflagClick(View view) {
myThread = new ColorChanger();
myThread.start();
}
public void onflagoffClick(View view) throws InterruptedException {
myThread.interrupt();
if(myThread.isAlive())
{
try {
myThread.join();
} catch(InterruptedException e){
}
}
else
{
mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.redColor));
}
mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.redColor));
}
}
I agree with the previous answer-ers, but propose a different solution.
First let me say that I recommend you stop using Runnables. In general posting a Runnable to a Handler is less efficient then sending a Message, although there are very rare exceptions to this rule.
Now, if we send Messages, what should we do? What we basically want to do is keep doing whatever we're doing until a condition is hit. A great way to do this is to write a Message Handler that receives a Message, does our work (setting the color), checks if we should keep going, and if so schedules a new Message in the future to do more work. Let's see how we might do this.
Assume the code below is inside an Activity.
private static final int MSG_UPDATE_COLOR = 1;
private static final int DELAY = 10; //10 millis
private final Object mLock = new Object();
private boolean mContinue = true;
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_UPDATE_COLOR:
synchronized (mLock) {
if (mContinue) {
setColor(Color.rgb(random.nextInt (255), random.nextInt (255), random.nextInt (255)));
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_COLOR, DELAY);
} else {
setColor(Color.RED);
}
}
break;
}
}
}
}
public void onflagClick(View view) {
mHandler.sendEmptyMessage(MSG_UPDATE_COLOR);
}
public void onflagoffClick(View view) throws InterruptedException {
synchronized (mLock) {
mContinue = false;
}
// cancel any pending update
mHandler.removeMessages(MSG_UPDATE_COLOR);
// schedule an immediate update
mHandler.sendEmptyMessage(MSG_UPDATE_COLOR);
}
Okay, so, what is happening here. We've created a Handler that will do all the color updates. We kick that off when our start event happens. Then the Message schedules a new message (and therefore color update) in ten milliseconds. When the stop event happens we reset a flag that the message handler reads to determine if a new update should be scheduled. We then unschedule all update messages because it might be scheduled for several milliseconds in the future and instead send an immediate message that does the final color update.
For bonus points we eliminate the use of a second thread which saves resources. Looking carefully I've used synchronized blocks, but these are actually unnecessary because everything is happening on the main thread. I included these just in case someone was changing mContinue from a background thread. Another great point of this strategy is that all color updates happen in one place in the code so it is easier to understand.
When you post to Handler, it will run your Runnable at some given time in the future. It is not immediate. It also works in a queue so the more times you post to Handler you are going to stack up the commands that will all get executed in order eventually.
You're facing a race condition because with Thread.sleep(10), the program is most likely stacking up a lot of Runnables to execute. They will run regardless of whether or not your Thread is running because they've been queued up to run on the main thread. Thread.sleep(100) or Thread.sleep(1000) doesn't have this issue simply because you're giving the system enough time to execute all color commands. However, it is still possible to have this issue if you pressed the off button at just the right time.
As DeeV told you, Handler sends Runnables to a Looper that is basically a Thread looping inside processing messages or runnables in each loop. You are queuing messaged to the main Looper and then you are sleeping your worker Thread. Its possible that you are sending for example 2 runnables in a row between each loop of your worker thread, but the main looper has only executed the last one so you cannot see each color as you want.
If you want a simple solution to make it work, you can use an Object or a CountDownLatch to synchronize your main Looperwith your worker Thread.
For example: Just before you will sleep your worker Thread you can do the next thing myLockObject.wait()
Then, you should change post(Runnable) to sendMessage(Message). In handleMessage from your Handler you can do myLockObject.notify() (Keep in mind that handleMessage will be executed inside the Looper that you have created your Handler or you can specify any Looper you want explicity). To obtain a new Message you should use myHandler.obtainMessage().
This will make your worker Thread wait your main Looperto process your runnable just before you wait X time until you post next color. Obviously you should create your new Object as a field of your Activity for example:
private myLockObject = new Object()

Android - How to create multiple threads to run at background?

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
}

Android Inception (A thread within a thread)

I have one function which queries a network server with a few "ping pongs" back and forth, and have written a custom handler to handle the message communication between my main UI thread and the communication thread (I was using AsyncTask for this, but as the program got more complex, I have decided to remove the communication code to its own class outside of the main activity).
Triggering a single instance of this thread communication from onCreate works perfectly, no problem.
I want this query to run on a regular timed basis -- in the background -- for the entire time the app is in use, so I've set up another thread called pollTimer, which I'm trying to use to call the OTHER thread at a regularly scheduled basis.
Obviously, it's crashing, or I wouldn't be posting this.
Is there a way to get a thread within a thread? Or put differently, trigger a thread from another thread?
Timer pollTimer = new Timer();
private void startPollTimer(){
pollTimer.scheduleAtFixedRate(new TimerTask(){
public void run(){
Log.d(TAG,"timer dinged");
//if the following is commented out, this "dings" every 6 seconds.
//if its not commented out, it crashes
threadedPoll();
}
}, 3120, 6000);
}
private void threadedPoll() {
testThread(asciiQueries,WorkerThreadRunnable.typeLogin);
}
edit: it would probably help to include the "testThread" function, which works by itself when called from onCreate, but does not make it when called from the Timer.
"WorkerThreadRunnable" is the massive chunk of code in its own class that has replaced the mess of having AsyncTask handle it inside the main activity.
private Handler runStatHandler = null;
Thread workerThread = null;
private void testThread(String[] threadCommands, int commandType){
if(runStatHandler == null){
runStatHandler = new ReportStatusHandler(this);
if(commandType == WorkerThreadRunnable.typeLogin){
workerThread = new Thread(new WorkerThreadRunnable(runStatHandler,threadCommands, WorkerThreadRunnable.typeLogin));
}
workerThread.start();
return;
}
//thread is already there
if(workerThread.getState() != Thread.State.TERMINATED){
Log.d(TAG,"thread is new or alive, but not terminated");
}else{
Log.d(TAG, "thread is likely deaad, starting now");
//there's no way to resurrect a dead thread
workerThread = new Thread(new WorkerThreadRunnable(runStatHandler));
workerThread.start();
}
}
You seem to be well on the way already - the nice thing about handlers, though, is that they aren't limited to the UI thread - so if you have a Handler declared by one thread, you can set it up to take asynchronous instructions from another thread
mWorkerThread = new WorkerThread()
private class WorkerThread extends Thread {
private Handler mHandler;
#Override
public void run() {
mHandler = new Handler(); // we do this here to ensure that
// the handler runs on this thread
}
public void doStuff() {
mHandler.post(new Runnable() {
#Override
public void run() {
// do stuff asynchronously
}
}
}
}
Hopefully that helps... if I'm totally off base on your problem let me know
Wots wrong with a sleep() loop? Why do you have pagefuls of complex, dodgy code when you could just loop in one thread?

Thread only loops once

ive been thinking about this for hours and im not closer to an solution!
My thread just stops looping when im fetching a message from an server for some reason, and works perfectly when im not doing it.
This works and prints refreshing every second:
public class ChatRoom extends Activity implements OnClickListener, Runnable {
private Thread t = new Thread(this);
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chatroom);
Button send = (Button) findViewById(R.id.send);
send.setOnClickListener(this);
Intent receiver = getIntent();
String host = receiver.getStringExtra("Host");
int port = receiver.getIntExtra("Port", 4456);
try
{
socket = new Socket(host, port);
this.receive = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
this.send = new PrintWriter(this.socket.getOutputStream(), true);
}
catch(IOException ioe) { System.out.println(ioe); }
t.start();
}
public void run()
{
String message = "";
while(true)
{
try
{
// message = receive.readLine(); BufferedReader
t.sleep(1000);
}
//catch(IOException ioe) { System.out.println(ioe); }
catch (NullPointerException npe) { System.out.println(npe); }
catch (InterruptedException e) { System.out.println(e); }
System.out.println("Refreshing...");
}
}
And when i use my commented code, it actually works and i get a message from the server but it loops just once! Why is that?
Output:
Server Message
Refreshing...
I get no Exception or errors, but i had an error before with some similar code that said that i cant change UI on other threads. So ive been looking at some runOnUiThread but it didnt make it better, and i dont know why it should :(
The method BufferedReader.readLine() blocks until a newline character is received. If there is no newline in your receiver stream it will block forever.
A few things here:
Swap from System.out.println("string"); to Log.d("tagname","string"); then look on DDMS for output lines.
I don't think you're creating a thread properly, and you certainly aren't providing any interface to kill it, which may cause issues when you test it. I would separate the thread into a new file, say NameOfThread:
//File "NameOfThread"
public class NameOfThread extends Thread{
//any fields you want here to mess with e.g.
private String message;
private boolean running;
public NameOfThread(){
message = "";
running = true;
}
#Override
public void run(){
while(running){
//do stuff
}
}
public void setRunning(boolean run){
running = run;
}
}
//When you want to call it
NameOfThread varThread = new NameOfThread();
varThread.start();
//when you want to kill the thread
varThread.setRunning(false);
You may think 'why bother with this whole running variable junk, I don't need it.' but how else will this thread end gracefully? There is another method of killing the thread properly, which is using InterruptedException and your cleanup code goes there, but that's just an alternative.
Try doing this first, then you'll need to sort out the message itself (the method you're using currently isn't great since readLine() will block until a line is received (meaning you'll get "Refreshing..." when you get a new line rather than once per second.
You're surely getting some exceptions thrown, you just can't see them cause you're trying to print them on the standard output, which is missing on Android. Your exception is handled correctly and the code finishes. To properly get the exception information use Logs, or just throw a RuntimeException. Hope this helps.

MultiThreading issues while programing for android

I am developing on Android but the question might be just as valid on any other Java platform.
I have developed a multi-threaded app. Lets say I have a first class that needs to do a time-intensive task, thus this work is done in another Thread.
When it's done that same Thread will return the time-intensive task result to another (3rd) class.
This last class will do something and return it's result to the first-starting class.
I have noticed though that the first class will be waiting the whole time, maybe because this is some kind of loop ?
Also I'd like the Thread-class to stop itself, as in when it has passed it's result to the third class it should simply stop. The third class has to do it's work without being "encapsulated" in the second class (the Thread one).
Anyone knows how to accomplish this ?
right now the experience is that the first one seems to be waiting (hanging) till the second and the third one are done :(
If you want to use threads rather than an AsyncTask you could do something like this:
private static final int STEP_ONE_COMPLETE = 0;
private static final int STEP_TWO_COMPLETE = 1;
...
private doBackgroundUpdate1(){
Thread backgroundThread = new Thread() {
#Override
public void run() {
// do first step
// finished first step
Message msg = Message.obtain();
msg.what = STEP_ONE_COMPLETE;
handler.sendMessage(msg);
}
}
backgroundThread.start();
}
private doBackgroundUpdate2(){
Thread backgroundThread = new Thread() {
#Override
public void run() {
// do second step
// finished second step
Message msg = Message.obtain();
msg.what = STEP_TWO_COMPLETE;
handler.sendMessage(msg);
}
}
backgroundThread.start();
}
private Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
switch(msg.what){
case STEP_ONE_COMPLETE:
doBackgroundUpdate2();
break;
case STEP_TWO_COMPLETE:
// do final steps;
break;
}
}
}
You would kick it off by calling doBackgroundUpdate1(), when this is complete it sends a message to the handler which kicks off doBackgroundUpdate2() etc.
Tiger ,
TiGer wrote:
When it's done that same Thread will
return the time-intensive task result
to another (3rd) class
Since thread runs asynchronously so your non-thread class can't be synced with your thread
Though to perform some action on an Activity you need an AsyncTask not A Thread
TiGer wrote:
maybe because this is some kind of
loop ?
Tiger do read more about Threads and concurrency
So the only answer I have for you now is ASYNCTASK
EDIT:
Also I'd like the Thread-class to stop
itself
Read this post's how-do-you-kill-a-thread-in-java
In ordinary Java, you would do this:
class MyTask implements Runnable {
void run() {
for (int i = 0; i < Integer.MAX; i++) {
if (i = Integer.MAX -1) {
System.out.println("done");
}
}
}
}
class MyMain {
public static void main(String[] argv) {
for (int i = 0; i < 10; i++) {
Thread t = new Thread(new MyTask());
t.start();
}
System.out.println("bye");
}
}
... that kicks off 10 threads. Notice that if you accidentally invoke t.run() instead of t.start(), your runnable executes in the main thread. Probably you'll see 'bye' printed before 10 'done'. Notice that the threads 'stop' when the the run() method of the Runnable you gave to them finishes.
I hope that helps you get your head around what it is you've got to co-ordinate.
The tricky part with concurrency is getting threads to communicate with each other or share access to objects.
I believe Android provides some mechanism for this in the form of the Handler which is described in the developer guide under designing for responsiveness.
An excellent book on the subject of concurrency in Java is Java Concurency in Practice.
if you want use AsyncTask rather then thread in android
I have resolve it using ASyncTask and Handler in Android the aim is that one task is execute after compilation of one task hear is code that show First load animation on view after compilation of that process it will goes on another page
class gotoparent extends AsyncTask<String,String,String>
{
#Override
protected String doInBackground(String... params) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Animation animation= AnimationUtils.loadAnimation(getApplicationContext(),R.anim.rotete);
lin2.startAnimation(animation);
}
});
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent i=new Intent(getApplicationContext(),ParentsCornor.class);
startActivity(i);
}
}, 1200);
}
}

Categories

Resources