1

私はアンドロイド開発の初心者です。画面上に円を描くこのコードを書きました。デバイスを動かすと、円が画面上を移動します。しかし、Nexus 7 デバイスでは非常に遅いです。パフォーマンスを向上させるのを手伝ってくれませんか?

public class MainActivity extends Activity implements SensorEventListener {

public static SensorManager mSensorManager;
public static Sensor accelerometer;
public static Sensor magnetometer;
public static float[] mAccelerometer = null;
public static float[] mGeomagnetic = null;
private SampleCircle sampleCircle;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    RelativeLayout layout = (RelativeLayout) findViewById(R.id.mainForm);
    sampleCircle = new SampleCircle(this);

    layout.addView(sampleCircle);


    layout.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            sampleCircle.setPoint(motionEvent.getX(), motionEvent.getY());
            return false;
        }
    });

    mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    accelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    magnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
}

@Override
protected void onResume() {
    super.onResume();

    mSensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_GAME);
    mSensorManager.registerListener(this, magnetometer, SensorManager.SENSOR_DELAY_GAME);
}

@Override
protected void onPause() {
    super.onPause();
    mSensorManager.unregisterListener(this, accelerometer);
    mSensorManager.unregisterListener(this, magnetometer);
}

@Override
public void onSensorChanged(SensorEvent event) {
    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
        mAccelerometer = event.values;
    }

    if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
        mGeomagnetic = event.values;
    }

    if (mAccelerometer != null && mGeomagnetic != null) {
        float R[] = new float[9];
        float I[] = new float[9];
        boolean success = SensorManager.getRotationMatrix(R, I, mAccelerometer, mGeomagnetic);

        if (success) {
            float orientation[] = new float[3];
            SensorManager.getOrientation(R, orientation);
            // at this point, orientation contains the azimuth(direction), pitch and roll values.
            double azimuth = 180 * orientation[0] / Math.PI;
            double pitch = 180 * orientation[1] / Math.PI;
            double roll = 180 * orientation[2] / Math.PI;

            sampleCircle.move((float) Math.floor(pitch), (float) Math.floor(roll));

        }
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public void onAccuracyChanged(Sensor sensor, int i) {
    System.out.println("Acc");
}

private class SampleCircle extends View {
    private Paint p = new Paint();
    {
        p.setColor(Color.RED);
        p.setStyle(Paint.Style.FILL);
    }
    private float y;
    private float x;

    public SampleCircle(Context context, float x, float y) {
        super(context);
        this.y = y;
        this.x = x;
    }

    public SampleCircle(Context context) {
        super(context);

    }

    public void setPoint(float x, float y) {
        this.x = x;
        this.y = y;
    }

    public void move(float x, float y) {
        this.x -= x;
        this.y -= y;

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(x, y, 50, p);
        invalidate();
    }
}

}

4

3 に答える 3

2

invalidate() を呼び出さないでください。onDraw メソッドでは、新しい位置に円を描画する場合にのみ呼び出します: setPoint() および move() メソッド内

于 2013-06-02T17:19:04.220 に答える
1

を呼び出すView.invalidate()と、 を呼び出してビューを再描画するようにオペレーティング システムに指示されますView.onDraw(Canvas)。したがって、 を呼び出すinvalidate()onDraw(...)、デバイスは常にビューの再描画でビジー状態になります。したがって、@pskink で提案されているように、およびメソッドView.invalidate()から呼び出す必要があります。ただし、最大の効率を得るには、許容範囲を追加する必要があります。これにより、動きが小さい場合に再描画が煩わされなくなります。SampleCircle.setPoint(...)SampleCircle.move(...)

于 2013-06-02T19:11:14.983 に答える
0

invalidate() は onSensorChanged(SensorEvent event); で呼び出す必要があります。顕著な変化が生じた場合のみ。これは確かにパフォーマンスを向上させるでしょう

于 2014-12-04T16:15:42.680 に答える