Thursday, January 3, 2013

Android Threading Made Easy

Googling shows me hundreds of different ways to achieve multithreading on Android. Sure, there's nothing inherently wrong with just using the generic Thread class, but it's a little bit lacking on the functionality department.

I'm going to cut all the bulls$*% and show you the easiest way to crack open an asynchronous task.


   1:      public void somefunction() {
   2:          new TaskDemo().execute();
   3:      }
   4:      
   5:      private class TaskDemo extends AsyncTask<Void, Void, Void> {
   6:          //Run your favorite task to be ran on a separate thread here!
   7:              return null;
   8:          }
   9:      }







Seriously, it's as easy as that. Now if you want to pass in parameters or get a meaningful value returned after the asynctask is completed, then you have to mess around with the generic types that goes inside AsyncTask. Otherwise, what you see above works perfectly.

But try to keep the principles of SCSR (Single-Class, Single-Responsibility) at heart. For example, the following code needs to be invoked on a separate thread:


   1:  public class PointControlActivity extends DDCMenuBaseActivity {
   2:      @Override
   3:      public void onCreate(Bundle savedInstanceState) {
   4:          super.onCreate(savedInstanceState);
   5:          setContentView(R.layout.point_control_activity);
   6:      }
   7:      
   8:      public void onClickPointRefresh(View v) {
   9:          Server soapService = new Server();
  10:          soapService.setUrl("http://192.168.0.19:7000");
  11:          VectorString pointID = new VectorString();
  12:          pointID.add("IO12345");
  13:          VectorpointReadDefaultValue pointResponse = soapService.ReadDefaultPoint(pointID);
  14:      }
  15:  }
  16:   
  17:  public class Server {
  18:      public String NAMESPACE = " http://www.lge.com/ddc";
  19:      public String url = "{0}";
  20:      public int timeOut = 8000;
  21:   
  22:      public void setTimeOut(int seconds) {
  23:          this.timeOut = seconds * 1000;
  24:      }
  25:   
  26:      public void setUrl(String url) {
  27:          this.url = url;
  28:      }
  29:   
  30:      public VectorpointReadDefaultValue ReadDefaultPoint(
  31:              VectorString pointIdentifier) {
  32:          return ReadDefaultPoint(pointIdentifier, null);
  33:      }
  34:   
  35:      public VectorpointReadDefaultValue ReadDefaultPoint(
  36:              VectorString pointIdentifier, List<HeaderProperty> headers) {
  37:   
  38:          SoapSerializationEnvelope soapEnvelope = new SoapSerializationEnvelope(
  39:                  SoapEnvelope.VER11);
  40:          soapEnvelope.implicitTypes = true;
  41:          soapEnvelope.dotNet = true;
  42:          SoapObject soapReq = new SoapObject("http://www.lge.com/ddc",
  43:                  "ReadDefaultPoint");
  44:          soapEnvelope.addMapping("http://www.lge.com/ddc",
  45:                  "pointReadDefaultValue[]",
  46:                  new VectorpointReadDefaultValue().getClass());
  47:          soapEnvelope.addMapping("http://www.lge.com/ddc", "pointIdentifier",
  48:                  new VectorString().getClass());
  49:          soapReq.addProperty("pointIdentifier", pointIdentifier);
  50:   
  51:          soapEnvelope.setOutputSoapObject(soapReq);
  52:          HttpTransportSE httpTransport = new HttpTransportSE(url, timeOut);
  53:          try {
  54:   
  55:              if (headers != null) {
  56:                  httpTransport.call("http://www.lge.com/ddc/ReadDefaultPoint",
  57:                          soapEnvelope, headers);
  58:              } else {
  59:                  httpTransport.call("http://www.lge.com/ddc/ReadDefaultPoint",
  60:                          soapEnvelope);
  61:              }
  62:              SoapObject result = (SoapObject) soapEnvelope.bodyIn;
  63:              SoapObject soapObject = (SoapObject) result
  64:                      .getPropertySafely("ReadDefaultPointResult");
  65:              VectorpointReadDefaultValue ReadDefaultPointResult = new VectorpointReadDefaultValue(
  66:                      soapObject);
  67:              return ReadDefaultPointResult;
  68:          } catch (Exception e) {
  69:              e.printStackTrace();
  70:          }
  71:          return null;
  72:      }
  73:  }

I could always create the thread on the code that initiates the network connection, but it's a much better idea to separate the code by creating an extra class for the task:

   1:  public class PointControlActivity extends DDCMenuBaseActivity {
   2:      @Override
   3:      public void onCreate(Bundle savedInstanceState) {
   4:          super.onCreate(savedInstanceState);
   5:          setContentView(R.layout.point_control_activity);
   6:      }
   7:      
   8:      public void onClickPointRefresh(View v) {
   9:          new DDCSoapRequestTask().execute();
  10:      }
  11:      
  12:      private class DDCSoapRequestTask extends AsyncTask<Void, Void, Void> {
  13:          @Override
  14:          protected Void doInBackground(Void... params) {
  15:              Server soapService = new Server();
  16:              soapService.setUrl("http://192.168.0.19:7000");
  17:              VectorString pointID = new VectorString();
  18:              pointID.add("IO12345");
  19:              VectorpointReadDefaultValue pointResponse = soapService.ReadDefaultPoint(pointID);
  20:              return null;
  21:          }
  22:      }
  23:  }

No comments:

Post a Comment