2010-11-29 67 views
0
public class SnowflakeWallpaper extends WallpaperService { 

// Limit of snowflakes per snowflake type; 4 types * 4 snowflake = 16 total 
// Should keep memory usage at a minimal 
static int SNOWFLAKE_AMOUNT = 4; 
Drawable drawWall; 
Rect wallBounds; 

// Draw all snowflakes off screen due to not knowing size of canvas at creation 
static int SNOW_START = -90; 

ArrayList<Snowflakes> snow = new ArrayList<Snowflakes>(); 
private final Handler mHandler = new Handler(); 


@Override 
public void onCreate() { 
    super.onCreate(); 
//WallpaperManager to pull current wallpaper 
WallpaperManager wManager = WallpaperManager.getInstance(this); 
drawWall = wManager.getFastDrawable(); 
wallBounds = drawWall.copyBounds(); 
} 

@Override 
public void onDestroy() { 
    super.onDestroy(); 
} 

@Override 
public Engine onCreateEngine() { 
    return new SnowEngine(); 
} 

class SnowEngine extends Engine { 

    private final Runnable mDrawSnow = new Runnable() { 
     public void run() { 
      drawFrame(); 
     } 
    }; 

    private boolean mVisible; 

    SnowEngine() { 

     if(snow.size() < 16){ 
    //Back snowflakes 
    for(int i = 0; i < SNOWFLAKE_AMOUNT; i++){ 
    snow.add(new Snowflakes(
    BitmapFactory.decodeResource(getResources(), 
    R.drawable.snowflakeback), 
    SNOW_START, 
    SNOW_START, 
    ((float)(Math.random() * 2) + 1)) // Fall speed initial setup, back slowest to front fastest potentially 
    ); 
    } 

    //MidBack snowflakes 
    for(int i = 0; i < SNOWFLAKE_AMOUNT; i++){ 
    snow.add(new Snowflakes(
    BitmapFactory.decodeResource(getResources(), 
    R.drawable.snowflakemid), 
    SNOW_START, 
    SNOW_START, 
    ((float)(Math.random() * 4) + 1) 
    )); 
    } 

    // Mid snowflakes 
    for(int i = 0; i < SNOWFLAKE_AMOUNT; i++){ 
    snow.add(new Snowflakes(
    BitmapFactory.decodeResource(getResources(), 
    R.drawable.snowflakemidfront), 
    SNOW_START, 
    SNOW_START, 
    ((float)(Math.random() * 8) + 1)) 
    ); 
    } 
    // Front snowflakes 
    for(int i = 0; i < SNOWFLAKE_AMOUNT; i++){ 
    snow.add(new Snowflakes(
    BitmapFactory.decodeResource(getResources(), 
    R.drawable.snowflake), 
    SNOW_START, 
    SNOW_START, 
    ((float)(Math.random() * 16) + 1)) 
    ); 
    } 
     } 
    } 

    @Override 
    public void onCreate(SurfaceHolder surfaceHolder) { 
     super.onCreate(surfaceHolder); 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     mHandler.removeCallbacks(mDrawSnow); 
    } 

    @Override 
    public void onVisibilityChanged(boolean visible) { 
     mVisible = visible; 
     if (visible) { 
      drawFrame(); 
     } else { 
      mHandler.removeCallbacks(mDrawSnow); 
     } 
    } 

    @Override 
    public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { 
     super.onSurfaceChanged(holder, format, width, height); 
     drawFrame(); 
    } 

    @Override 
    public void onSurfaceCreated(SurfaceHolder holder) { 
     super.onSurfaceCreated(holder); 
    } 

    @Override 
    public void onSurfaceDestroyed(SurfaceHolder holder) { 
     super.onSurfaceDestroyed(holder); 
     mVisible = false; 
     mHandler.removeCallbacks(mDrawSnow); 
    } 

    /* 
    * Update the screen with a new frame 
    */ 
    void drawFrame() { 
     final SurfaceHolder holder = getSurfaceHolder(); 

     /* 
     * if the snow goes too low or too right, reset; 
     */ 
     for(int i = 0; i < snow.size(); i++){ 
     if(snow.get(i).getX() > holder.getSurfaceFrame().width()){ 
      snow.get(i).setX(-65); 
     } 
     if(snow.get(i).getY() > holder.getSurfaceFrame().height()){ 
      snow.get(i).setY(-69); 
     } 
     } 

     // Test if the array was just create; true - randomly populate snowflakes on screen 
     if(snow.get(1).getX() < -70){ 
     for(int i = 0; i < snow.size(); i++){ 
      snow.get(i).setX((int)(Math.random() * getSurfaceHolder().getSurfaceFrame().width() +1)); 
      snow.get(i).setY((int)(Math.random() * getSurfaceHolder().getSurfaceFrame().height() + 1)); 
     } 
     } 


     // Change snowflake x & y 
     for(int i = 0; i < snow.size(); i++){ 
     snow.get(i).delta(); 
     } 

     Canvas c = null; 
     try { 
      c = holder.lockCanvas(); 
      if (c != null) { 

       // call to draw new snow position 
       drawSnow(c); 
      } 
     } finally { 
      if (c != null) holder.unlockCanvasAndPost(c); 
     } 

     // Reschedule the next redraw 
     mHandler.removeCallbacks(mDrawSnow); 
     if (mVisible) { 
      mHandler.postDelayed(mDrawSnow, 1000/100); 
     } 
    } 

    /* 
    * Draw the snowflakes 
    */ 
    void drawSnow(Canvas c) { 
     c.save(); 

     // Draw bg 
     //********** add code to pull current bg and draw that instead of black. Maybe set this in config? 
     if(drawWall == null){ 
     c.drawColor(Color.BLACK); 
     }else{ 
     drawWall.copyBounds(wallBounds); 
     drawWall.draw(c); 
     } 

     /* 
     * draw up the snow 
     */ 
     for(int i = 0; i < snow.size(); i++){ 
     c.drawBitmap(snow.get(i).getImage(), snow.get(i).getX(), snow.get(i).getY(), null); 
     } 

     c.restore(); 
    } 
} 

}关于如何优化此代码的任何想法?我似乎无法拿出任何工作

+3

什么问题?它太慢了吗?它使用了太多的CPU吗?它闪烁吗?它甚至工作吗? – Gabe 2010-11-29 06:40:11

回答

1

同样的问题加布 - 有什么问题吗?

一些一般想法: *您应该避免在构造函数中做大量工作。你的构造函数做了大量的工作,而不是在init/setup方法中。更容易独立于实例创建进行基准测试/配置文件。

  • 你在很多地方使用Math.random - 我假设你是单线程的,但Math.random是同步的。根据javadocs:“如果许多线程需要以很快的速度生成伪随机数,它可能会减少争用每个线程有自己的伪随机数发生器”

  • 您正在使用Math.random让你双倍,然后相乘,然后添加,然后投射。这看起来很浪费。任何方式获得更少的操作?

  • 您似乎有一些划分 - 请参见行“mHandler.postDelayed(mDrawSnow,1000/100);”。当然,这可能是编译或JIT离开,但你应该避免在性能关键代码中划分(它比乘法慢得多)。所以任何一个常量的div都可以被1/C乘以静态值来代替。

  • 您有大量的重复访问器方法调用(在某些情况下,几乎所有的重复)。见SNIPPIT:

for(int i = 0; i < snow.size(); i++){ 
    if(snow.get(i).getX() > holder.getSurfaceFrame().width()){ 
     snow.get(i).setX(-65); 
    } 
    if(snow.get(i).getY() > holder.getSurfaceFrame().height()){ 
     snow.get(i).setY(-69); 
    } 
    } 

,可以储存“holder.getSurfaceFrame()宽()在临时/局部变量(每绘图循环也许曾经假设你的面是可调整大小的用户。 ),你也可能在一个局部变量店snow.get(I)。更重要的是(风格),您可以使用增强的for循环如雪是一个ArrayList,所以使用

for (Snow mySnow : snow) { 
// Do something with mySnow 
} 

希望这有助于。祝你好运!

+0

@加贝和诺亚,它确实工作,CPU使用率似乎很低(没有做太多的分析,仍然学习,但根据我的机器人的电池使用率在2和3%之间),有时似乎很慢,但大多是我相信它会放慢主屏幕上的用户界面。例如,向左或向右滑动似乎已经减慢。没有什么特别明显的,但有时似乎有点迟缓。我实施诺亚斯的建议和更新。 – jwp 2010-11-29 07:52:28