2016-04-25 42 views
1

我正在開發一個使用SurfaceView監聽觸摸事件的遊戲。 SurfaceView中的onTouchEvent方法適用於很多設備,但在某些設備中,有時它不會被調用(Moto X Style就是其中之一),我的應用程序也會停止響應。Android SurfaceView onTouchEvent沒有被調用

我想這可能是由於onTouchEvent捱餓導致主線程重載。

可能一些Android的專家在這裏給我一些提示,以減少對主線程的負載,如果是擠破頭,或可能有一些其他原因可能導致這個

的代碼是非常複雜,但還是我米張貼一些,如果你想通過它去

GameLoopThread

public class GameLoopThread extends Thread{ 
    private GameView view; 
    // desired fps 
    private final static int MAX_FPS = 120; 
    // maximum number of frames to be skipped 
    private final static int MAX_FRAME_SKIPS = 5; 
    // the frame period 
    private final static int FRAME_PERIOD = 1000/MAX_FPS; 

    private boolean running = false; 

    public GameLoopThread(GameView view){ 
     this.view = view; 
    } 

    public void setRunning(boolean running){ 
     this.running = running; 
    } 

    public boolean isRunning() { 
     return running; 
    } 
    @Override 
    public void run() { 
     Canvas canvas; 
     long beginTime;  // the time when the cycle begun 
     long timeDiff;  // the time it took for the cycle to execute 
     int sleepTime;  // ms to sleep (<0 if we're behind) 
     int framesSkipped; // number of frames being skipped 

     while (running) { 
      canvas = null; 
      // try locking the canvas for exclusive pixel editing 
      // in the surface 
      try { 
       canvas = view.getHolder().lockCanvas(); 
       synchronized (view.getHolder()) { 
        beginTime = System.nanoTime(); 
        framesSkipped = 0; // resetting the frames skipped 
        // update game state 
        // render state to the screen 
        // draws the canvas on the panel 
        this.view.draw(canvas); 
        // calculate how long did the cycle take 
        timeDiff = System.nanoTime() - beginTime; 
        // calculate sleep time 
        sleepTime = (int)(FRAME_PERIOD - timeDiff/1000000); 

        if (sleepTime > 0) { 
         // if sleepTime > 0 we're OK 
         try { 
          // send the thread to sleep for a short period 
          // very useful for battery saving 
          Thread.sleep(sleepTime); 
         } catch (InterruptedException e) {} 
        } 

        while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) { 
         // update without rendering 
         // add frame period to check if in next frame 
         sleepTime += FRAME_PERIOD; 
         framesSkipped++; 
        } 
       } 
      } 
      finally { 
       // in case of an exception the surface is not left in 
       // an inconsistent state 
       view.getHolder().unlockCanvasAndPost(canvas); 
      } // end finally 
     } 
    } 
} 

GameView

public class GameView extends SurfaceView { 
    ArrayList<Bitmap> circles = new ArrayList<>(); 
    int color; 
    public static boolean isGameOver; 

    public GameLoopThread gameLoopThread; 
    Circle circle;  // Code for Circle class is provided below 

    public static int score = 0; 
    public static int stars = 0; 

    final Handler handler = new Handler(); 

    int remainingTime; 

    boolean oneTimeFlag; 

    Bitmap replay; 
    Bitmap home; 
    Bitmap star; 

    int highScore; 
    boolean isLeaving; 

    public GameView(Context context, ArrayList<Bitmap> circles, int color) { 
     super(context); 
     this.circles = circles; 
     this.color = color; 

     oneTimeFlag = true; 
     gameLoopThread = new GameLoopThread(GameView.this); 

     getHolder().addCallback(new SurfaceHolder.Callback() { 
      @Override 
      public void surfaceCreated(SurfaceHolder holder) { 
       if (!gameLoopThread.isRunning()) { 
        gameLoopThread.setRunning(true); 
        gameLoopThread.start(); 
       } 
      } 

      @Override 
      public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 

      } 

      @Override 
      public void surfaceDestroyed(SurfaceHolder holder) { 
       gameLoopThread.setRunning(false); 
       gameLoopThread = new GameLoopThread(GameView.this); 
      } 
     }); 

     initializeCircles(); 
     if(!gameLoopThread.isRunning()) { 
      gameLoopThread.setRunning(true); 
      gameLoopThread.start(); 
     } 
    } 

    public void initializeCircles() { 
     ArrayList<String> numbers = new ArrayList<>(); 
     for(int i=0;i<10;i++) 
      numbers.add(i+""); 

     Random random = new Random(); 
     int position = random.nextInt(4); 
     numbers.remove(color + ""); 

     int p1 = position; 

     int r1 = Integer.valueOf(numbers.get(random.nextInt(9))); 
     numbers.remove(r1+""); 

     int r2 = Integer.valueOf(numbers.get(random.nextInt(8))); 
     numbers.remove(r2 + ""); 

     int r3 = Integer.valueOf(numbers.get(random.nextInt(7))); 

     ArrayList<Bitmap> bitmaps = new ArrayList<>(); 

     if(position == 0) { 
      bitmaps.add(circles.get(color)); 
      bitmaps.add(circles.get(r1)); 
      bitmaps.add(circles.get(r2)); 
      bitmaps.add(circles.get(r3)); 
     } 
     else if(position == 1) { 
      bitmaps.add(circles.get(r1)); 
      bitmaps.add(circles.get(color)); 
      bitmaps.add(circles.get(r2)); 
      bitmaps.add(circles.get(r3)); 
     } 
     else if(position == 2) { 
      bitmaps.add(circles.get(r1)); 
      bitmaps.add(circles.get(r2)); 
      bitmaps.add(circles.get(color)); 
      bitmaps.add(circles.get(r3)); 
     } 
     else { 
      bitmaps.add(circles.get(r1)); 
      bitmaps.add(circles.get(r2)); 
      bitmaps.add(circles.get(r3)); 
      bitmaps.add(circles.get(color)); 
     } 

     numbers = new ArrayList<>(); 
     for(int i=0;i<10;i++) 
      numbers.add(i+""); 

     position = random.nextInt(4); 
     numbers.remove(color + ""); 

     r1 = Integer.valueOf(numbers.get(random.nextInt(9))); 
     numbers.remove(r1 + ""); 

     r2 = Integer.valueOf(numbers.get(random.nextInt(8))); 
     numbers.remove(r2 + ""); 

     r3 = Integer.valueOf(numbers.get(random.nextInt(7))); 

     if(position == 0) { 
      bitmaps.add(circles.get(color)); 
      bitmaps.add(circles.get(r1)); 
      bitmaps.add(circles.get(r2)); 
      bitmaps.add(circles.get(r3)); 
     } 
     else if(position == 1) { 
      bitmaps.add(circles.get(r1)); 
      bitmaps.add(circles.get(color)); 
      bitmaps.add(circles.get(r2)); 
      bitmaps.add(circles.get(r3)); 
     } 
     else if(position == 2) { 
      bitmaps.add(circles.get(r1)); 
      bitmaps.add(circles.get(r2)); 
      bitmaps.add(circles.get(color)); 
      bitmaps.add(circles.get(r3)); 
     } 
     else { 
      bitmaps.add(circles.get(r1)); 
      bitmaps.add(circles.get(r2)); 
      bitmaps.add(circles.get(r3)); 
      bitmaps.add(circles.get(color)); 
     } 

     circle = new Circle(this, bitmaps, circles, p1, position, color, getContext()); 
    } 

    @Override 
    public void draw(Canvas canvas) { 
     if(canvas != null) { 
      super.draw(canvas); 
      canvas.drawColor(Color.WHITE); 

      if(!isGameOver && timer != null) 
       stopTimerTask(); 
      try { 
       circle.draw(canvas); 
      } catch (GameOverException e) { 
       isGameOver = true; 
       if(isLeaving) 
        gameOver(canvas); 
       else if(GameActivity.counter > 0) { 
        gameOver(canvas); 
        GameActivity.counter++; 
       } else { 
        if (oneTimeFlag) { 
         int size1 = 200 * GameActivity.SCREEN_HEIGHT/1280; 
         int size2 = 125 * GameActivity.SCREEN_HEIGHT/1280; 
         float ratio = (float) GameActivity.SCREEN_HEIGHT/1280; 

         replay = GameActivity.decodeSampledBitmapFromResource(getResources(), R.drawable.replay, size1, size1); 
         home = GameActivity.decodeSampledBitmapFromResource(getResources(), R.drawable.home, size2, size2); 
         continueButton = GameActivity.decodeSampledBitmapFromResource(getContext().getResources(), R.drawable.button, (int) (540 * ratio), (int) (100 * ratio)); 
         star = GameActivity.decodeSampledBitmapFromResource(getContext().getResources(), R.drawable.star1, (int) (220 * ratio), (int) (220 * ratio)); 

         int w = (int) ((float) GameActivity.SCREEN_WIDTH * 0.9); 
         oneTimeFlag = false; 
        } 

        if (askPurchaseScreen == 2) { 
         gameOver(canvas); 
        } else { 
         canvas.drawColor(Circle.endColor); 
        } 
       } 
      } 
     } 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     float x = event.getX(); 
     float y = event.getY(); 
     circle.onTouch(x, y); 
     return true; 
    } 
} 

public class Circle { 
    int x; 
    int y1; 
    int y2; 
    public static float speedY1 = 12.5f*(float)GameActivity.SCREEN_HEIGHT/1280; 
    public static float speedY2 = 12.5f*(float)GameActivity.SCREEN_HEIGHT/1280; 
    ArrayList<Bitmap> bitmaps; 
    GameView gameView; 
    int p1;  // Position of required circle in slot 1 
    int p2;  // Position of required circle in slot 2 
    int color; 
    int tempColor; 
    int width; 
    Context context; 

    // Centers of required circle 
    float centerX1; 
    float centerX2; 
    float centerY1; 
    float centerY2; 

    ArrayList<Bitmap> circles = new ArrayList<>(); 
    boolean touchedFirst; 
    boolean touchedSecond; 
    int count1 = 1;  // Slot 1 circle radius animation 
    int count2 = 1;  // Slot 2 circle radius animation 

    float tempSpeedY1; 
    float tempSpeedY2; 
    boolean stopY1; 
    boolean stopY2; 
    int barCounter = 1; 
    int loopCount = 0; 

    int endGameCount = 0; // Count to move circle upwards 
    double limit; 
    float endRadiusSpeed; 
    int endSlot; // Where you died 
    int endRadiusCount = 0; // Count to increase circle radius 
    int barEndCounter = 1; 

    final Handler handler = new Handler(); 
    boolean exception; 
    public static int endColor; 

    public Circle(GameView gameView, ArrayList<Bitmap> bitmaps, ArrayList<Bitmap> circles, int p1, int p2, int color, Context context) { 
     this.gameView = gameView; 
     this.bitmaps = bitmaps; 
     this.circles = circles; 
     this.p1 = p1; 
     this.p2 = p2; 
     this.color = color; 
     this.context = context; 

     width = GameActivity.SCREEN_WIDTH/4 - 10; 
     x = 10; 
     y1 = 0; 
     y2 = -(GameActivity.SCREEN_HEIGHT + width)/2; 

     centerX1 = x + p1 * (10 + width) + width/2; 
     centerY1 = y1 + width/2; 

     centerX2 = x + p2 * (10 + width) + width/2; 
     centerY2 = y2 + width/2; 
    } 

    public void update() throws GameOverException { 
     y1+= speedY1; 
     y2+= speedY2; 

     centerY1+= speedY1; 
     centerY2+= speedY2; 

     float ratio = (float)GameActivity.SCREEN_HEIGHT/1280; 
     limit = width/(20*ratio); 

     if(y1 >= gameView.getHeight()) { 
      loopCount++; 

      if(touchedFirst) 
       touchedFirst = false; 
      else { 
       speedY1 = speedY2 = -(12.5f * ratio); 
       endColor = bitmaps.get(p1).getPixel(width/2, width/2); 

       endGameCount += 1; 
       endSlot = 1; 
      } 

      if(endGameCount == 0) { 
       if (stopY1) { 
        tempSpeedY1 = speedY1; 
        speedY1 = 0; 
        ArrayList<Integer> numbers = new ArrayList<>(); 
        for (int i = 0; i < 10; i++) { 
         if (i != color) 
          numbers.add(i); 
        } 
        tempColor = numbers.get(new Random().nextInt(9)); 
       } 

       y1 = -(gameView.getWidth()/4 - 10); 
       count1 = 1; 
       setBitmaps(1); 
      } 
     } 
     else if(y2 >= gameView.getHeight()) { 
      loopCount++; 

      if(touchedSecond) 
       touchedSecond = false; 
      else { 
       speedY1 = speedY2 = -(12.5f * ratio); 
       endColor = bitmaps.get(p2 + 4 
       ).getPixel(width/2, width/2); 
       endGameCount += 1; 
       endSlot = 2; 
      } 

      if(endGameCount == 0) { 
       if (stopY2) { 
        tempSpeedY2 = speedY2; 
        speedY2 = 0; 
       } 

       y2 = -(gameView.getWidth()/4 - 10); 
       count2 = 1; 
       setBitmaps(2); 
      } 
     } 
    } 

    public void setBitmaps(int slot) { 
     ArrayList<String> numbers = new ArrayList<>(); 
     for(int i=0;i<10;i++) 
      numbers.add(i+""); 

     Random random = new Random(); 
     int position = random.nextInt(4); 
     numbers.remove(color + ""); 

     int r1 = Integer.valueOf(numbers.get(random.nextInt(9))); 
     numbers.remove(r1+""); 

     int r2 = Integer.valueOf(numbers.get(random.nextInt(8))); 
     numbers.remove(r2 + ""); 

     int r3 = Integer.valueOf(numbers.get(random.nextInt(7))); 

     if(position == 0) { 
      bitmaps.set((slot - 1)*4, circles.get(color)); 
      bitmaps.set((slot - 1)*4 + 1, circles.get(r1)); 
      bitmaps.set((slot - 1)*4 + 2, circles.get(r2)); 
      bitmaps.set((slot - 1)*4 + 3, circles.get(r3)); 
     } 
     else if(position == 1) { 
      bitmaps.set((slot - 1)*4, circles.get(r1)); 
      bitmaps.set((slot - 1)*4 + 1, circles.get(color)); 
      bitmaps.set((slot - 1)*4 + 2, circles.get(r2)); 
      bitmaps.set((slot - 1)*4 + 3, circles.get(r3)); 
     } 
     else if(position == 2) { 
      bitmaps.set((slot - 1)*4, circles.get(r1)); 
      bitmaps.set((slot - 1)*4 + 1, circles.get(r2)); 
      bitmaps.set((slot - 1)*4 + 2, circles.get(color)); 
      bitmaps.set((slot - 1)*4 + 3, circles.get(r3)); 
     } else { 
      bitmaps.set((slot - 1)*4,circles.get(r1)); 
      bitmaps.set((slot - 1)*4 + 1,circles.get(r2)); 
      bitmaps.set((slot - 1)*4 + 2,circles.get(r3)); 
      bitmaps.set((slot - 1)*4 + 3,circles.get(color)); 
     } 
     if(slot == 1) { 
      p1 = position; 
      centerX1 = x+position*(10 + width) + width/2; 
      centerY1 = y1 + width/2; 
     } 
     else if(slot == 2) { 
      p2 = position; 
      centerX2 = x+position*(10 + width) + width/2; 
      centerY2 = y2 + width/2; 
     } 
    } 

    public void onTouch(float X, float Y) { 
     int radius = (gameView.getWidth()/4 - 10)/2; 

     if(endGameCount == 0) { 
      if ((X >= centerX1 - radius) && (X <= centerX1 + radius) && (Y >= centerY1 - radius) && (Y <= centerY1 + radius)) { 
       GameView.score++; 
       touchedFirst = true; 
       centerX1 = centerY1 = -1; 

       if(p1 == (timerCount - 1) && timer != null && starSlot == 1) { 
        GameView.stars++; 
        starCollected = true; 
        timerCount = 0; 
        stopTimerTask(0); 
       } 
      } else if ((X >= centerX2 - radius) && (X <= centerX2 + radius) && (Y >= centerY2 - radius) && (Y <= centerY2 + radius)) { 
       GameView.score++; 
       touchedSecond = true; 
       centerX2 = centerY2 = -1; 

       if(p2 == (timerCount - 1) && timer != null && starSlot == 2) { 
        GameView.stars++; 
        starCollected = true; 
        timerCount = 0; 
        stopTimerTask(0); 
       } 
      } else { 
       endSlot = 0; 
       if ((Y >= centerY1 - radius) && (Y <= centerY1 + radius)) { 
        endSlot = 1; 
        if (X >= 10 && X <= 10 + 2 * radius) { 
         p1 = 0; 
         centerX1 = 10 + radius; 
        } else if (X >= 20 + 2 * radius && X <= 20 + 4 * radius) { 
         p1 = 1; 
         centerX1 = 20 + 3 * radius; 
        } else if (X >= 30 + 4 * radius && X <= 30 + 6 * radius) { 
         p1 = 2; 
         centerX1 = 30 + 5 * radius; 
        } else if (X >= 40 + 6 * radius && X <= 40 + 8 * radius) { 
         p1 = 3; 
         centerX1 = 40 + 2 * radius; 
        } else 
         endSlot = 0; 
       } else if ((Y >= centerY2 - radius) && (Y <= centerY2 + radius)) { 
        endSlot = 2; 
        if (X >= 10 && X <= 10 + 2 * radius) { 
         p2 = 0; 
         centerX2 = 10 + radius; 
        } else if (X >= 20 + 2 * radius && X <= 20 + 4 * radius) { 
         p2 = 1; 
         centerX2 = 20 + 3 * radius; 
        } else if (X >= 30 + 4 * radius && X <= 30 + 6 * radius) { 
         p2 = 2; 
         centerX2 = 30 + 5 * radius; 
        } else if (X >= 40 + 6 * radius && X <= 40 + 8 * radius) { 
         p2 = 3; 
         centerX2 = 40 + 2 * radius; 
        } else 
         endSlot = 0; 
       } 
       if (endSlot != 0) { 
        speedY1 = speedY2 = 0; 
        limit = endGameCount = 6; 

        if (endSlot == 1) { 
         endColor= bitmaps.get(p1).getPixel(width/2, width/2); 
        } else { 
         endColor = bitmaps.get(p2 + 4).getPixel(width/2, width/2); 
        } 
       } 
      } 

      if (GameView.score % 5 == 0 && GameView.score <= 110 && barCounter == 1) { 
       float ratio = (float)GameActivity.SCREEN_HEIGHT/1280; 
       speedY1 += ratio*0.5; 
       speedY2 += ratio*0.5; 
      } 

      if (GameView.score > 0 && GameView.score % 15 == 14) { 
       if(isOddScore) 
        stopY1 = true; 
       else 
        stopY2 = true; 
      } 

      if (GameView.score > 0 && GameView.score % 15 == 0 && barCounter == 1) { 
       if(isOddScore) 
        stopY2 = true; 
       else 
        stopY1 = true; 
      } 

      if (GameView.score % 15 == 1) 
       barCounter = 1; 
     } 
    } 
    public void draw(Canvas canvas) throws GameOverException { 
     GameView.isGameOver = false; 
     if(exception) 
      throw new GameOverException(color); 
     update(); 

     for(int i=0;i<bitmaps.size();i++) { 
      if(i<4) { 
       Rect rect = new Rect(x+i*(10 + width),y1,(x+width)*(i+1),y1+width); 
       if(endGameCount == Math.ceil(limit) && endSlot == 1) { 
        if(i == p1) { 
         endRadiusCount += 1; 
         if (endRadiusCount > 23) { 
          star.recycle(); 
          loopCount = loopCount%starInterval; 
          Cryptography.saveFile((loopCount + "").getBytes(), context, "interval"); 
          endGameCount = 0; 
          exception = true; 
          throw new GameOverException(color); 
         } 

         rect = new Rect(x + i * (10 + width) - endRadiusCount*(int)Math.ceil(endRadiusSpeed), y1 - endRadiusCount*(int)Math.ceil(endRadiusSpeed), (x + width) * (i + 1) + endRadiusCount*(int)Math.ceil(endRadiusSpeed), y1 + width + endRadiusCount*(int)Math.ceil(endRadiusSpeed)); 
         canvas.drawBitmap(bitmaps.get(i), null, rect, null); 
        } 
       } 

       // TOUCH ANIMATION : DIMINISH CIRCLE 
       else if(i==p1 && touchedFirst) { 
        rect = new Rect(x + i * (10 + width) + 3*count1 + ((int)speedY1-15), y1 + 3*count1 + ((int)speedY1-15), (x + width) * (i + 1) - 3*count1 - ((int)speedY1-15), y1 + width - 3*count1 - ((int)speedY1-15)); 
        canvas.drawBitmap(bitmaps.get(i), null, rect, null); 
        count1++; 
       } 

       else if(endSlot != 2) { 
        canvas.drawBitmap(bitmaps.get(i), null, rect, null); 
        if(timerCount > 0 && starSlot == 1) { 
         int size = width * 30/50; 
         int difference = (width - size)/2; 
         Rect starRect = new Rect(x + (timerCount - 1) * (10 + width) + difference, y1 + difference, (x + width) * (timerCount) - difference, y1 + width - difference); 
         canvas.drawBitmap(star, null, starRect, null); 
        } 
       } 
      } 
      if(i >= 4) { 
       Rect rect = new Rect(x + (i % 4) * (10 + width), y2, (x + width) * ((i % 4) + 1), y2 + width); 
       if(endGameCount == Math.ceil(limit) && endSlot == 2) { 
        if((i%4)==p2) { 
         endRadiusCount += 1; 
         if (endRadiusCount > 23) { 
          star.recycle(); 
          loopCount = loopCount%starInterval; 
          Cryptography.saveFile((loopCount + "").getBytes(), context, "interval"); 
          endGameCount = 0; 
          exception = true; 
          throw new GameOverException(color); 
         } 

         rect = new Rect(x + (i % 4) * (10 + width) - endRadiusCount*(int)Math.ceil(endRadiusSpeed), y2 - endRadiusCount*(int)Math.ceil(endRadiusSpeed), (x + width) * ((i % 4) + 1) + endRadiusCount*(int)Math.ceil(endRadiusSpeed), y2 + width + endRadiusCount*(int)Math.ceil(endRadiusSpeed)); 
         canvas.drawBitmap(bitmaps.get(i), null, rect, null); 
        } 
       } 
       else if((i%4)==p2 && touchedSecond) { 
        rect = new Rect(x + (i % 4) * (10 + width) + 3*count2 + ((int)speedY1-15), y2 + 3*count2 + ((int)speedY1-15), (x + width) * ((i % 4) + 1) - 3*count2 - ((int)speedY1-15), y2 + width - 3*count2 - ((int)speedY1-15)); 
        canvas.drawBitmap(bitmaps.get(i), null, rect, null); 
        count2++; 
       } 
       else if(endSlot != 1) { 
        canvas.drawBitmap(bitmaps.get(i), null, rect, null); 
        if(timerCount > 0 && starSlot == 2) { 
         int size = width * 30/50; 
         int difference = (width - size)/2; 
         Rect starRect = new Rect(x + (timerCount - 1) * (10 + width) + difference, y2 + difference, (x + width) * (timerCount) - difference, y2 + width - difference); 
         canvas.drawBitmap(star, null, starRect, null); 
        } 
       } 
      } 
     } 
     Rect src = new Rect(circles.get(color).getWidth()/2 - 10,circles.get(color).getHeight()/2 - 10,circles.get(color).getWidth()/2 + 10,circles.get(color).getHeight()/2 + 10); 
     Rect dst; 

     Paint paint = new Paint(); 
     paint.setColor(Color.WHITE); 
     paint.setTextAlign(Paint.Align.RIGHT); 
     paint.setTypeface(Typeface.SANS_SERIF); 
     paint.setTextSize(72 * ratio); 
     canvas.drawText(GameView.score + " ", GameActivity.SCREEN_WIDTH, width/2, paint); 

     dst = new Rect(5,5, (int) (120 * ratio - 5), (int) (120 * ratio - 5)); 
     canvas.drawBitmap(star,null,dst,null); 
     paint.setTextAlign(Paint.Align.LEFT); 
     canvas.drawText("" + GameView.stars, 120 * ratio, width/2, paint); 
    } 
} 
+0

發佈一些代碼.. –

+0

您不必刪除並重新發布你的問題。只需編輯您的[原始文章](http://stackoverflow.com/questions/36828309/surfaceview-ontouchevent-not-working)將會將其打到活動隊列的頂部。 –

+0

@salihkallai發佈了代碼。檢查一下 –

回答

0

成功解決了這個問題。無法想象,與我考慮複雜的問題相比,解決方案會非常簡單。只需將幀速率從120降低到90,並猜測它的功能就像魅力一樣!

由於高幀速率,在SurfaceView忙着做所有的繪圖和的onTouchEvent()方法只好捱餓

0

不要覆蓋draw()。這是用來渲染視圖,而不是表面的,你一般不應該重寫,即使你創建一個自定義查看方法:

當實現一個視圖,執行的onDraw(android.graphics.Canvas)而不是重寫此方法。

SurfaceViews有兩個部分,Surface和View。視圖部分像其他視圖一樣處理,但通常只是佈局中的透明「洞」。 Surface是一個單獨的層,默認情況下,它位於View層後面。無論您在Surface上繪製「透過」透明孔顯示。

通過重寫draw(),您在視圖UI失效時正在使用視圖。你也從render線程調用draw(),所以你在Surface上繪圖,但是默認的Z順序你看不到,因爲View內容是完全不透明的。您將通過不在兩個不同的圖層中繪製所有內容來減少對UI線程的影響。

除非您故意繪製視圖,否則最好避免將SurfaceView完全子類化,並將其用作成員。

因爲您的繪圖代碼是同步的,所以兩個繪製過程不會同時執行。這意味着您的視圖圖層繪製調用將阻止等待表面圖層渲染完成。 Canvas上的Canvas渲染不是硬件加速的,所以如果你觸及很多像素,它可能會變慢,UI線程將不得不等待它運行。這並不會那麼糟糕,但是當你在睡覺的時候,你仍然堅持互斥體,這意味着主UI線程運行的唯一機會來自循環周圍的短暫瞬間。線程調度程序不保證公平性,所以完全可以通過這種方式扼殺主UI線程。

如果將@override draw()更改爲myDraw()事情應該會好一些。您可能只需按照一般原則將睡眠呼叫移出同步模塊,或者工作到eliminate it entirely。您可能還想考慮使用custom View而不是SurfaceView。

在一個不相關的音符,你應該避免這樣做每一次更新:

Random random = new Random(); 

的原因,指出here

+0

首先感謝分享知識。我將'@override draw()'方法替換爲'doDrawing()'(也取代了隨機隨機=新的隨機();'調用,但仍然發生同樣的事情發生在Moto X Style(Android 6.0,2560 x 1440分辨率),有時它可以正常工作,而有時觸摸事件根本不起作用,應用程序也會停止響應 我試過的所有其他設備工作正常,請問這是由於其大分辨率或什麼問題。我被困在這裏2天以來 –

+0

如果主UI線程卡住了,你需要找出卡住的位置,你可以通過附加一個調試器來解決它,當它粘住或者看着堆棧跟蹤ANR報告中不要忘記將睡眠呼叫移出同步塊,最好的做法是儘可能少地鎖定鎖。 – fadden

相關問題