关于如何优化这段代码有什么想法吗?我似乎想不出任何有效的办法

发布于 2024-10-04 21:33:16 字数 5390 浏览 0 评论 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();
    }
}

}

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();
    }
}

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

变身佩奇 2024-10-11 21:33:16

与加布同样的问题 - 问题是什么?

一些总体想法:
* 您应该避免在构造函数中做大量工作。你的构造函数做了大量的工作,这些工作应该(恕我直言)在某些 init/setup 方法中进行。更容易独立于实例创建进行基准测试/分析。

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

  • 您正在使用 Math.random ,它可以为您提供一个双精度值,然后乘法,然后加法,然后铸造。这看起来很浪费。有什么办法可以减少操作数吗?

  • 您似乎有一些划分 - 请参阅“mHandler.postDelayed(mDrawSnow, 1000 / 100);”行。当然,这可能会被编译或 JIT 掉,但您应该避免在性能关键代码中进行除法(它比乘法慢得多)。因此,任何由常量组成的 div 都可以通过乘以 1 / C 作为静态来替换。

  • 您有很多重复的访问器方法调用(在某些情况下几乎所有都是重复的)。请参阅片段:

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

您应该将“holder.getSurfaceFrame().width() 存储在临时/本地变量中(假设用户可以调整表面大小,则可能每个绘制循环一次)。您也可以将snow.get(i) 存储在本地变量中。更好的是(风格)你可以使用增强的 for 循环,因为雪是一个 ArrayList,所以使用

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

希望这有帮助。

Same question as Gabe - what's the problem?

Some general thoughts:
* You should avoid doing lots of work in a constructor. Your constructor does a ton of work that should (imho) be in some init/setup method instead. Easier to benchmark / profile there independently from instance creation.

  • You're using Math.random in many places - I assume you are singly threaded, but Math.random is synchronized. Per the javadocs: " if many threads need to generate pseudorandom numbers at a great rate, it may reduce contention for each thread to have its own pseudorandom-number generator"

  • You're using Math.random which gets you a double, then multiplying, then adding, then casting. This looks wasteful. Any way to get fewer ops?

  • You seem to have some division - see line "mHandler.postDelayed(mDrawSnow, 1000 / 100);". Sure, that's probably compiled or JIT'd away, but you should avoid division in performance critical code (it's far slower than multiplying). So any div by a constant can be replaced by multiplying by 1 / C as a static.

  • You have lots of repeat accessor method calls (in some cases nearly all are repeat). See 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);
     }
    }

You should store "holder.getSurfaceFrame().width() in a temporary / local var (perhaps once per draw loop assuming your surface is resizable by the user). You might also store snow.get(i) in a local var. Better yet (style) you can use the enhanced for loop as snow is an ArrayList. So use

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

Hope this helps. Good luck!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文