1

Short story:
I need to move a bit of code out of my UI thread and into a background thread, and I need to be able to pass five variable values into that background thread and receive five values back from it. I'm hoping someone can provide a simple working example, pretending that the code below is my code and the bit between the commented lines is what needs to be moved.

Longer story:
Part of the code in my UI thread is taking about fifteen seconds to complete. The screen freezes during this period. I don't mind that the screen freezes because the user doesn't need to interact with the screen at that point anyway. The problem is that I also have an OnKeyListener in my UI thread and it doesn't approve of the delay. If the user presses any keyboard key during the fifteen-second delay, it will cause an ANR (application not responding) prompt to appear about five seconds later. I need to move the time-consuming code into a separate thread where it can run in the background. I've spent about thirteen hours trying to figure out how to do this using AsyncTask and other methods but have been unable to figure out how to pass five variable values into the thread and receive five values back from it. I'm hoping someone can provide a simple working example, pretending that the code below is my code and the bit between the commented lines is what needs to be moved.

       myButton.setOnClickListener(new OnClickListener()
       {
          public void onClick(View arg0)
          {
          Integer userNum1 = 12; //pretend these numbers are user inputted (ever-changing)
          Integer userNum2 = 8;
          Integer userNum3 = 2;
          Integer userNum4 = 31;
          Integer userNum5 = 17;
          Integer userMultiplier = 9;
          //-----------------------------
             for (int i = 0; i < 15; i++)
             {
             userNum1 = userNum1 * userMultiplier;
             userNum2 = userNum2 * userMultiplier;
             userNum3 = userNum3 * userMultiplier;
             userNum4 = userNum4 * userMultiplier;
             userNum5 = userNum5 * userMultiplier;

             try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}   
             }
          //-----------------------------
          String myString1 = String.valueOf(userNum1);
          String myString2 = String.valueOf(userNum2);
          String myString3 = String.valueOf(userNum3);
          String myString4 = String.valueOf(userNum4);
          String myString5 = String.valueOf(userNum5);
          }
       });  



EDIT:
Here's what I ended up doing to solve this problem:

public Integer myTaskDone = 0;  
public Integer userNum1 = 0;    
public Integer userNum2 = 0;    
public Integer userNum3 = 0;    
public Integer userNum4 = 0;    
public Integer userNum5 = 0;
public Integer userMultiplier = 0;
public String[] valueTransporter = new String[20];





myButton.setOnClickListener(new OnClickListener()
{
   public void onClick(View arg0)
   {
   userNum1 = 12;
   userNum2 = 8;
   userNum3 = 2;
   userNum4 = 31;
   userNum5 = 17;
   userMultiplier = 9;

   valueTransporter[0] = String.valueOf(userNum1);
   valueTransporter[1] = String.valueOf(userNum2);
   valueTransporter[2] = String.valueOf(userNum3);
   valueTransporter[3] = String.valueOf(userNum4);
   valueTransporter[4] = String.valueOf(userNum5);
   valueTransporter[5] = String.valueOf(userMultiplier);

   new myTask().execute(valueTransporter);
   }
});  





//Had to move the last section of code into this new thread, otherwise the code would have executed before myTask finished.
//All this thread does is frequently check myTaskDone to see if it equals 1 (if it does equal 1, the last section of code will be executed).
final Handler mHandler = new Handler();
new Thread(new Runnable()
{
@Override
   public void run()
   {
      while (true)
      {
         try
         {
         Thread.sleep(10); 
            mHandler.post(new Runnable()
            {
            @Override
               public void run() 
               {
                  if (myTaskDone == 1)
                  {
                  myTaskDone = 0;
                  String myString1 = String.valueOf(userNum1);
                  String myString2 = String.valueOf(userNum2);
                  String myString3 = String.valueOf(userNum3);
                  String myString4 = String.valueOf(userNum4);
                  String myString5 = String.valueOf(userNum5);
                  }
               }
            });
         } catch (Exception e) {}
      }
   }  
}).start();




public class myTask extends AsyncTask<String,String,String[]> 
{
    @Override

    protected String[] doInBackground(String... valueTransporter)
    {

    //Our values have been transported in via valueTransporter. Put those values back into variables so we can work on them.    
    Integer userNum1 = Integer.parseInt(valueTransporter[0]);   
    Integer userNum2 = Integer.parseInt(valueTransporter[1]);
    Integer userNum3 = Integer.parseInt(valueTransporter[2]);
    Integer userNum4 = Integer.parseInt(valueTransporter[3]);
    Integer userNum5 = Integer.parseInt(valueTransporter[4]);
    Integer userMultiplier = Integer.parseInt(valueTransporter[5]);

       //Do work
       //-----------------------------
       for (int i = 0; i < 15; i++)
       {
       userNum1 = userNum1 * userMultiplier;
       userNum2 = userNum2 * userMultiplier;
       userNum3 = userNum3 * userMultiplier;
       userNum4 = userNum4 * userMultiplier;
       userNum5 = userNum5 * userMultiplier;

       try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}   
       }
       //-----------------------------

    //Now that the work has been done on the values, load them back into valueTransporter.
    valueTransporter[0] = String.valueOf(userNum1);
    valueTransporter[1] = String.valueOf(userNum2);
    valueTransporter[2] = String.valueOf(userNum3);
    valueTransporter[3] = String.valueOf(userNum4);
    valueTransporter[4] = String.valueOf(userNum5);

    return valueTransporter;
    }

    protected void onPostExecute(String[] valueTransporter) 
    {
    //Get the values out of valueTransporter and into the original variables used by the UI thread.
    userNum1 = Integer.parseInt(valueTransporter[0]);   
    userNum2 = Integer.parseInt(valueTransporter[1]);
    userNum3 = Integer.parseInt(valueTransporter[2]);
    userNum4 = Integer.parseInt(valueTransporter[3]);
    userNum5 = Integer.parseInt(valueTransporter[4]);

    myTaskDone = 1;
    }

}  
Eric Glass
  • 141
  • 3
  • 12
  • 2
    you can pass the values to the constructor of asynctask and to return you can check this http://stackoverflow.com/questions/16752073/how-do-i-return-a-boolean-from-asynctask – Raghunandan Jun 07 '13 at 16:14
  • @Raghunandan : I can see a way that I can pass five values into the background thread but I don't see how I can get five values back from it. – Eric Glass Jun 07 '13 at 16:44
  • have you checked the link above using the interface method suggested in the accepted answer – Raghunandan Jun 07 '13 at 16:45
  • @Raghunandan : I can't make sense of it. What part of it do I need? What part is sending back the variable values? – Eric Glass Jun 07 '13 at 16:51

1 Answers1

0

You can clean this up by putting the outputs on MyTask:

  • create a field for each output value on MyTask
  • set their values in onPostExecute()
  • change 'boolean myTaskDone' to 'MyTask finishedTask'
  • change 'myTaskDone = 1' to 'finishedTask = this'
  • change 'if (myTaskDone == 1)' to 'if (finishedTask != null)'

Then you can just pull the values off the task object, and you can delete valueTransporter.

Also, typically rather than having a loop, you can call a method from onPostExecute() with all the output values (or the MyTask) as parameters, and that method can do whatever comes next.

rightparen
  • 1,693
  • 10
  • 15