LANDSCAPE Orientation is causing my thread to run twice- why is that?

edited March 2014 in Android Mode

So in my quest to learn, I have been playing with Threading via this Processing wiki post: Which works fine in Java. It also works fine in Android mode via the emulator, UNLESS i specify a landscape orientation.

Here's my code (which is mostly pulled from the above linked tutorial:

SimpleThread thread;

void setup()
{

  orientation(LANDSCAPE);
  thread = new SimpleThread(1000,"I'm a thread! ");
  thread.start();
}

void draw()
{
  background(255);
  fill(0);

}

 class SimpleThread extends Thread
 {

  boolean running;           // Is the thread running?  Yes or no?
  int wait;                  // How many milliseconds should we wait in between executions?
  String id;                 // Thread name
  int count;                 // counter

  // Constructor, create the thread
  // It is not running by default
  SimpleThread (int w, String s)
  {
    wait = w;
    running = false;
    id = s;
    count = 0;
  }//end SimpleThread

  int getCount()
  {
    return count;
  }//end getCount

  // Overriding "start()"
  void start ()
  {
    // Set running equal to true
    running = true;
    // Print messages
    println("Starting thread (will execute every " + wait + " milliseconds.)"); 
    // Do whatever start does in Thread, don't forget this!
    super.start();
    //run();
  }//end start()


  // We must implement run, this gets triggered by start()
  void run ()
  {
    while (running && count < 10)
    {
      println(id + ": " + count);
      count++;
      // Ok, let's wait for however long we should wait
      try
      {
        sleep((long)(wait));
      }
      catch (Exception e)
      {
      }
    }
    System.out.println(id + " thread is done!");  // The thread is done when we get to the end of run()
  }//end run()


  // Our method that quits the thread
  void quit()
  {
    System.out.println("Quitting."); 
    running = false;  // Setting running to false ends the loop in run()
    // IUn case the thread is waiting. . .
    interrupt();
  }//end quit()
}//end class

Here's my console output:

debug: Starting thread (will execute every 1000 milliseconds.) I'm a thread! : 0 I'm a thread! : 1 I'm a thread! : 1 I'm a thread! : 2 I'm a thread! : 2 I'm a thread! : 3 I'm a thread! : 3 I'm a thread! : 4 I'm a thread! : 4 I'm a thread! : 5 I'm a thread! : 5 I'm a thread! : 6 I'm a thread! : 6 I'm a thread! : 7 I'm a thread! : 7 I'm a thread! : 8 I'm a thread! : 8 I'm a thread! : 9 I'm a thread! : 9 I'm a thread! thread is done! I'm a thread! thread is done!

If you comment out orientation(LANDSCAPE); or change it to orientation(PORTRAIT);, it works fine. And by that I mean you only see, say, "I'm a thread! : 1" once, instead of twice.

Any ideas why?

I'm using Processing 2.0.3 if that helps.

Answers

  • edited March 2014

    It's a mean trick, but setup() is actually run twice sometimes. I forget why, exactly. Something to do with setting the window and then starting over.

    Anyway, you could try to add a boolean flag that checks if your thread has been created...

    SimpleThread thread;
    boolean thread_can_start = true;
    
    void setup() {
      orientation(LANDSCAPE);
      if(thread_can_start){
        thread = new SimpleThread(1000,"I'm a thread! ");
        thread.start();
        thread_can_start = false;
      }
    }
    
  • edited March 2014 Answer ✓

    I have a theory: The orientation() function may simulate a physical device rotation, and it may not do so until the main thread has a pause. When an Android application is rotated, the Activity is killed and re-started. If this is the case, then this is why your setup() is run twice - you request a screen rotation, you start a thread, the screen rotation occurs, the activity is restarted, your old thread is still there, and then you run through it again (but the orientation is already landscape, so the cycle doesn't repeat itself...).

    This may very well be the case, and it could explain some of the issues that people have been having with orientation(). Although @TfGuy44's solution may work, I suggest that you consider trying the fix suggested in this post (it is perhaps more elegant).

    Note: I haven't tested this, but I have reasonable confidence in my theory.

    @TfGuy44: I think that setup() running twice has more to do with not having the size() function the first call in setup() (in Java mode, at least). I may be wrong, though...

  • edited March 2014

    TfGuy - hmmm, that didn't work. I'll have to investigate this some more. I appreciate the advice though. Maybe the pieces are there and I can get this to work

    calsign- your answer popped up as i was replying to TfGuy, so I'll go back and read it. Just wanted to edit to clarify who I was responding to

  • edited March 2014

    @krashe1313, your latest comment further reinforces my theory - indeed, if the activity is restarted, then your global variables are wiped as well, rendering @TfGuy44's check useless! (It was still good advice, though...)

  • edited March 2014

    @calsign well your method of manually changing the manifest worked. Thank you.

    I do have a follow up question; if on changing the orientation of the screen is simulating a physical rotation, thus the activity gets killed then restarted, now in landscape, how can two identical instances of the same object (SimpleThread) exist with out throwing a flag that says "hey, you have 2 instances of the same object with the exact same name"?

    Thanks

  • Answer ✓

    The two identical SimpleThreads are separate instances. They can both have a variable with the same name without the VM complaining. In fact, the two instances may even exist on separate Linux processes, and thus they can have no interaction (without tapping into Android's process-checking APIs).

    When the screen is rotated and the activity is restarted, the old activity is completely gone - it's as if the user has closed out of the sketch and restarted it. The old thread probably sticks around long enough to run its course, but the reference to it in the old activity is long gone. As far as the VM is concerned, the old thread and the new thread, although identical in code, are two completely separate threads.

    For comparison, you don't encounter problems when running the same sketch twice, even though the sketch contains all of the same variables, now, do you?

    Disclaimer: My understanding of the internal workings of the Android VM is far from complete, but I think my explanation should be sufficient (and sufficiently accurate) to answer your question.

  • edited March 2014

    @calsign Fantastic. This was my assumption, but I wasn't entirely sure. My understanding of the internal workings of Android VM, Java, Processing, life in general, etc, lol, is VERY far from complete. So thank you for taking the time to explain it.

    @TfGuy44 Thanks also for your little trick. Although it didn't work in this instance, it's one I'll keep for reference.

Sign In or Register to comment.