Ondraw для пользовательского представления бесконечно зацикливается на Android - PullRequest
5 голосов
/ 12 октября 2011

Функция OnDraw для моего пользовательского представления вызывается бесконечно и зацикливается !!В чем может быть причина ??

Вот мой пользовательский вид: -

public class Balls extends View{

    private static final String TAG = "BallsView";

    private int mMode = READY;
    public static final int PAUSE = 0;
    public static final int READY = 1;
    public static final int RUNNING = 2;
    public static final int LOSE = 3;

    private final Paint mPaint = new Paint();
    private double mUx = 0.1;
    private double  mUy = 2;
    private double mVy;
    private double mVx;
    private double mSx;
    private double mSy;
    private double mRange;
    private float mX1;
    private float mY1;
    private int mX2;
    private int mY2;
    private int mDx;
    private int mDy;
    Time t;
    float mAngle;
    private final double mGravity = -9.8;

    private long mLastTime;

    private double mT;

    private Canvas mCanvas = null;



    public Balls(Context context, AttributeSet attrs, int defStyle){
        super(context, attrs, defStyle);
        setFocusable(true);
        setWillNotDraw(false);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE); 
        mPaint.setStrokeWidth(10); 
        mPaint.setAntiAlias(true); 
        mPaint.setStrokeCap(Cap.ROUND); 
        //mPaint.setColor(0xff00ffff);
        mPaint.setARGB(255, 0, 255, 0);

        mLastTime = System.currentTimeMillis();


    }
    public Balls(Context context, AttributeSet attrs) {
        super(context, attrs);
         setFocusable(true);
         setWillNotDraw(false);
          mPaint.setStyle(Paint.Style.FILL_AND_STROKE); 
          mPaint.setStrokeWidth(10); 
          mPaint.setAntiAlias(true); 
          mPaint.setStrokeCap(Cap.ROUND); 
          mPaint.setColor(0xff00ffff);

    }

     @Override
    public void onDraw(Canvas canvas) {
         Log.w(this.getClass().getName(),"onDraw of Balls called");
      super.onDraw(canvas);
      mCanvas = canvas;

      if(mCanvas!= null)
          Log.w(this.getClass().getName(),"Canvas is not null");

    }

Этот вид раздувается следующим образом в другом упражнении: -

mBalls = (Balls) findViewById(R.id.balls);

Этопредставление помещается в XML-файл внутри относительного представления, а относительное представление является дочерним элементом представления горизонтальной прокрутки.

Ответы [ 4 ]

5 голосов
/ 12 октября 2011

Здесь нет бесконечного цикла.То, что происходит, - это то, что ОС перерисовывает вашу деятельность как можно быстрее.Когда ваша деятельность перерисовывается, она перерисовывает все дочерние представления.Поскольку в вашем коде очень мало вычислений, из того, что я вижу здесь, он работает очень быстро и, вероятно, перерисовывается со скоростью> 30 FPS.Ваше сообщение журнала делает это, как будто существует бесконечный цикл, когда его нет.На самом деле в вашем методе onDraw даже нет цикла.

Чтобы проиллюстрировать, что происходит, попробуйте это.Добавьте защищенного члена drawCount в свой класс Balls и установите для него значение 0:

protect int drawCount = 0;

Затем добавьте drawCount в конец вашего onDraw сообщения журнала

 public void onDraw(Canvas canvas){
       drawCount++;
       Log.w(this.getClass().getName(),"onDraw of Balls called. Total draws:" + Integer.toString(drawCount));
  ...
  }

То, что вы должны увидеть, это то, что каждое сообщение журнала будет отображать различный drawCount.

Если вы хотите получить фантазию и рассчитать частоту кадров своего приложения, вы можете измерить время с момента первого розыгрыша, а затем разделить drawCount на сколько времени прошло, что даст вам оценку вашей деятельностифреймрейт.

3 голосов
/ 12 октября 2011

onDraw () вызов get при аннулировании. Функция Invalidate () get вызывается, когда представление или его родитель чувствуют необходимость изменить и изменить свое состояние.

2 голосов
/ 22 июня 2017

onDraw(Canvas) вызывается слишком часто, как в бесконечном цикле, это ненормально. обычно его следует вызывать от 1 до 3 раз, если нет следующих invalidate или изменений макета. причины бесконечного цикла могут быть:
1, вы позвонили invalidate или postInvalidate где-то.
2, макет родителя или сестры постоянно меняется.
3, используется View.LAYER_TYPE_SOFTWARE, es. setLayerType (View.LAYER_TYPE_SOFTWARE, null).
Примечательно, что LAYER_TYPE_SOFTWARE вызовет onDraw(), как в цикле.

0 голосов
/ 07 ноября 2018

Для меня это происходило, потому что у меня был некоторый код, который изменял интерфейс внутри переопределенного DispatchDraw ..

...