title: Why is a simple background animation too much work for my main thread?
body: <p>I am working on an Android app and on my main/launcher screen (the screen you are brought to when you initially start the app) I want to have a simple animation in the background. Specifically, right now I have a few buttons centered in the window and in the background I have some small stars doing a looping translate animation from top left to bottom right of the screen, behind everything else. It's non-interactive and simply repeats once it is finished. I have nine of these stars, and they aren't terribly large. However, when I try to run the app (this does happen on the emulator mostly, but it also happens on my phone, just less often) I get messages like these:</p>
  
  <pre><code>I/Choreographer(  632): Skipped 33 frames!  The application may be doing too much work on its main thread.
  </code></pre>
  
  <p>It seems as though what it is actually doing is trying to line up my stars so they are moving at the same time. When I start the animation I have them running at offsets from each other i.e. a star is going by every .5 seconds or so, but when it skips frames it lines them up so the stars (starting with a few but eventually ending with all of the stars) are starting and ending their animations at the exact same time. This looks pretty silly, as there is a large mass of stars moving at the same speed through the background all at the same time. I'm guessing having them all move at the same exact time is less work for the processor than having them run at offsets, which may be why it is doing it that way. </p>
  
  <p>I know that I can't do UI activity on anything except the main thread, but this seems a bit silly. All I am doing is a simple, repeated animation in the background of my app and it is "too much work". <strong>So, is there a way to do the animation which will result in less work so my animation will actually look the way it is supposed to?</strong> I'm attempting to write a simple game, but if it can't even manage to animate a few objects in a repeatable, non-interactive fashion I can't imagine how it can handle an interactive game. But I've played interactive games on Android, so I must be missing something. Anyone have any tips?</p>
  
  <p>P.S. here is the code I am using to do my animations.<br>
  Animation code: </p>
  
  <pre><code>public static Animation _runAnimation(Activity ctx, View target) {
        Animation animation = AnimationUtils.loadAnimation(ctx, R.anim.slide_right);
        animation.setFillAfter(true);
        target.startAnimation(animation);
        return animation;
      }
  </code></pre>
  
  <p>Animation layout: (slide_right.xml) </p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  
  &lt;set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator" &gt;
      &lt;translate android:fromXDelta="-20%p" android:toXDelta="100%p" android:duration="2000" android:repeatCount="infinite" /&gt;
      &lt;translate android:fromYDelta="-20%p" android:toYDelta="100%p" android:duration="2000" android:repeatCount="infinite" /&gt;
      &lt;!--rotate android:pivotX="0" android:toDegrees="360" android:duration="2000" android:repeatCount="10000" /--&gt;//this doesn't cause the stars to spin in place, it rotates them around a point. 
  
  &lt;/set&gt;
  </code></pre>
  
  <p>Actual calls: </p>
  
  <pre><code>public Activity _launcher = this; //the activity
  public Handler handler = new Handler(); //a handler
  handler.postDelayed(new Runnable() { 
                   public void run() { 
                       _runAnimation(_launcher, findViewById(R.id.star1)); 
                   } 
              }, 10);
  handler.postDelayed(new Runnable() { 
                   public void run() { 
                       _runAnimation(_launcher, findViewById(R.id.star2)); 
                   } 
              }, 700);
  handler.postDelayed(new Runnable() { 
               public void run() { 
                   _runAnimation(_launcher, findViewById(R.id.star3)); 
               } 
          }, 1600); 
  handler.postDelayed(new Runnable() { 
               public void run() { 
                   _runAnimation(_launcher, findViewById(R.id.star4)); 
               } 
          }, 2500); 
  handler.postDelayed(new Runnable() { 
               public void run() { 
                   _runAnimation(_launcher, findViewById(R.id.star5)); 
               } 
          }, 3300);
  handler.postDelayed(new Runnable() { 
               public void run() { 
                   _runAnimation(_launcher, findViewById(R.id.star6)); 
               } 
          }, 3700);
  
  handler.postDelayed(new Runnable() { 
               public void run() { 
                   _runAnimation(_launcher, findViewById(R.id.star7)); 
               } 
          }, 4400);
  
  handler.postDelayed(new Runnable() { 
               public void run() { 
                   _runAnimation(_launcher, findViewById(R.id.star8)); 
               } 
          }, 5300);
  
  handler.postDelayed(new Runnable() { 
               public void run() { 
                   _runAnimation(_launcher, findViewById(R.id.star9)); 
               } 
          }, 5800);
  </code></pre>