0

I'm developing an android app that requires to make UI changes according to a background thread processing results, I tried the following code at first:

        Thread run_time = new Thread (){
            public void run(){
                ConnectToServer connect = new ConnectToServer(null);
                while(true){
                        String server_response = connect.getServerResponse();
                        if(!server_response.equals(null)){  
                            setResponse(server_response);
                            response_received();
                    }
                }
            }
        };
        run_time.start();

but my App crashes because i tried to make a UI changes from that background thread, then I tried that way:

        runOnUiThread(new Runnable() {
            public void run(){
                ConnectToServer connect = new ConnectToServer(null);
                while(true){
                        String server_response = connect.getServerResponse();
                        if(!server_response.equals(null)){
                            setResponse(server_response);
                            response_received();
                    }
                }
            }
        });

but i got that exception:

01-29 16:42:17.045: ERROR/AndroidRuntime(605): android.os.NetworkOnMainThreadException
01-29 16:42:17.045: ERROR/AndroidRuntime(605):     at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1084)
01-29 16:42:17.045: ERROR/AndroidRuntime(605):     at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:151)
01-29 16:42:17.045: ERROR/AndroidRuntime(605):     at libcore.io.IoBridge.recvfrom(IoBridge.java:503)
01-29 16:42:17.045: ERROR/AndroidRuntime(605):     at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488)
01-29 16:42:17.045: ERROR/AndroidRuntime(605):     at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:46)

and after search i found that I must run the code as AsyncTask to avoid these problems, but when attempting to use it i found that it's must be used with small tasks only not like a thread that runs in the background all the run_time.

So, what's the best day to run a thread or a task in the background in whole the run_time and also reflect it's changes to the UI.

MRefaat
  • 515
  • 2
  • 8
  • 22

4 Answers4

4

EDIT:

For Long running network work you have a few options.

First and formost check the android docs on this topic:

http://developer.android.com/training/basics/network-ops/index.html

Next, I generally use Services for this type of thing:

https://developer.android.com/guide/components/services.html

I will point you at the vogella tutorial for this as well:

http://www.vogella.com/tutorials/AndroidServices/article.html

For communication from threads/asynctasks/services to the UI use Handlers:

Use Handlers:

static public class MyThread extends Thread {
    @Override
    public void run() {
      try {
        // Simulate a slow network
        try {
          new Thread().sleep(5000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        downloadBitmap = downloadBitmap("http://www.devoxx.com/download/attachments/4751369/DV11");
        // Updates the user interface
        handler.sendEmptyMessage(0);
      } catch (IOException e) {
        e.printStackTrace();
      } finally {

      }
    }
  }
    handler = new Handler() {
      @Override
      public void handleMessage(Message msg) {
        // cal uiMethods here...
        imageView.setImageBitmap(downloadBitmap);
//        dialog.dismiss();
      }

    };

Taken from this tutorial:

http://www.vogella.com/tutorials/AndroidBackgroundProcessing/article.html

You can make this more interesting by defining constant_codes which corespond to the desired action:

private int DO_THIS = 0x0;
private int DO_THAT = 0x1;

// in your UI:

 public void handleMessage(Message msg) {
        // cal uiMethods here...
        switch(msg.what()){
           case(DO_THIS):
             // do stuff
             break;
           case(DO_THAT):
            // do other stuff
            break;
        }
      }

// in your thread:

Message m = handler.obtainMessage(DO_THIS);
handler.sendMessage(m);

If the thread code (asynch task, service etc...) is separate from the UI you can use Broadcasts to pass the data between the two and then use Handlers from there to act on the UI thread.

giro
  • 421
  • 1
  • 7
  • 19
Nathaniel D. Waggoner
  • 2,856
  • 2
  • 19
  • 41
0

you need to use handlers here is documntation: https://developer.android.com/training/multiple-threads/communicate-ui.html

Darko Rodic
  • 1,010
  • 3
  • 10
  • 27
0

Use this code - it may contain compile time error you have to do it correct

public class MainActivity extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    Connect connect = new Connect();
    connect.execute();
}

class Connect extends AsyncTask<Void, String, Void>
{
    @Override
    protected Void doInBackground(Void... params) 
    {
        ConnectToServer connect = new ConnectToServer(null);
        while(true)
        {
            String server_response = connect.getServerResponse();
            if(!server_response.equals(null))
            {  
                publishProgress(server_response);
                //setResponse(server_response);
                response_received();
            }
        }
        return null;
    }

    @Override
    protected void onProgressUpdate(String... values) {

        super.onProgressUpdate(values);
        setResponse(values[0]);
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
    }
}
}
Rajan
  • 1,069
  • 1
  • 9
  • 17
0

You need "handlers" along with "loopers" for optimization Example:

public void myMethod(){
    Thread background = new Thread(new Runnable(){
        @Override
        public void run(){
            Looper.prepare();
            //Do your server process here
            Runnable r=new Runnable() {
                   @Override
                   public void run() {
                                            //update your UI from here
                   }
            };
            handler.post(r);
            Looper.loop();
        }
    });
    background.start();
}

And of course this is without using AsyncTask

Jerry Wattre
  • 204
  • 2
  • 8
  • I don't know but this code doesn't make me receive any server responses, The app doesn't crash but also doesn't act, may be the something with the way i created the handler, i just make it `Handler handle = new Handle()` before `Looper.prepare()` , is that OK ? – MRefaat Jan 30 '14 at 08:58
  • 1
    @MRefaat : Yea thats fine...receiving the server response is a different thing, that you have to make sure that it receives something...but after you receive...say once you received something you have a flag that becomes true, so in(//update your UI) have a condition if(flag==true){ then you can send your data to a method on the UI thread or just toast the response for confirmation} else nothing... The app dosen't act cuz i think the server dosen't send any response – Jerry Wattre Jan 31 '14 at 02:46