一定時間ごとに処理をする - タイマー機能の実装 (TimerとTimerTaskの利用)

こちらで作成したアプリケーションにタイマーを追加し、一定時間ごとに描画内容が変わる動作にします。

プロジェクト設定、UI

こちらと同様です。

コード

下記のコードを記述します。

MainActivity.java

package com.iPentec.canvasdraw;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends Activity {
  Timer timer ;
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    timer = new Timer();
    TimerTask timerTask = new MyTimerTask(this);
    timer.scheduleAtFixedRate(timerTask, 0, 50);
  }

  public void InvalidateScreen(){
    MyView myview1 = (MyView)findViewById(R.id.myView1);
    myview1.invalidate();
  }
  
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
  }
}
解説
  timer = new Timer();
  TimerTask timerTask = new MyTimerTask(this);
  timer.scheduleAtFixedRate(timerTask, 0, 50);
上記がタイマーに関するコードです。タイマー動作の手順は、Timerクラスのインスタンスを作成し、scheduleAtFiedRate()メソッドを呼び出します。第一引数にはタイマーのタスクであるTimerTaskオブジェクトのインスタンスを与えます。第二引数はタイマーの実行開始までの時間を設定します。今回は遅延はないため0とします。第三引数はタイマーのインターバルです。値はミリ秒を指定します。今回は50ミリ秒ごとに処理を実行します。

MyTimerTask.java

package com.iPentec.canvasdraw;

import java.util.Timer;
import java.util.TimerTask;
import android.os.Handler;
import android.content.Context;

public class MyTimerTask extends TimerTask {
  private Handler handler;
  private Context context;
   
  public MyTimerTask(Context context) {
    handler = new Handler();
    this.context = context;
  }
   
  @Override
  public void run() {
    handler.post(new Runnable() {
      @Override
      public void run() {
        ((MainActivity)context).InvalidateScreen();
      }
    });
  }

}
解説
タイマーのタスクを処理するクラスです。
  @Override
  public void run() {
    handler.post(new Runnable() {
      @Override
      public void run() {
        ((MainActivity)context).InvalidateScreen();
      }
    });
  }
タイマーのタスクが実行されているサブスレッドからUIのあるメインスレッドへアクセスをすると不正アクセスになるため、メインスレッドへPostして処理を実行します。handlerはコンストラクタでインスタンスが作成されたためhandler.postはメインスレッドへ送られます。タイマーのタスクでは"((MainActivity)context).InvalidateScreen();"が実行されるため、MainActivity.javaのInvalidateScreenメソッドが呼び出され画面が更新されます。

MyTimerTask.java

package com.iPentec.canvasdraw;

import java.util.Random;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;

/**
 * TODO: document your custom view class.
 */
public class MyView extends View {
  private String mExampleString; // TODO: use a default from R.string...
  private int mExampleColor = Color.RED; // TODO: use a default from R.color...
  private float mExampleDimension = 0; // TODO: use a default from R.dimen...
  private Drawable mExampleDrawable;

  private TextPaint mTextPaint;
  private float mTextWidth;
  private float mTextHeight;

  public MyView(Context context) {
    super(context);
    init(null, 0);
  }

  public MyView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(attrs, 0);
  }

  public MyView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(attrs, defStyle);
  }

  private void init(AttributeSet attrs, int defStyle) {

  }

  private void invalidateTextPaintAndMeasurements() {
    mTextPaint.setTextSize(mExampleDimension);
    mTextPaint.setColor(mExampleColor);
    mTextWidth = mTextPaint.measureText(mExampleString);

    Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
    mTextHeight = fontMetrics.bottom;
  }

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    
    // TODO: consider storing these as member variables to reduce
    // allocations per draw cycle.
    int paddingLeft = getPaddingLeft();
    int paddingTop = getPaddingTop();
    int paddingRight = getPaddingRight();
    int paddingBottom = getPaddingBottom();

    int contentWidth = getWidth() - paddingLeft - paddingRight;
    int contentHeight = getHeight() - paddingTop - paddingBottom;
    
    Rect r = new Rect(0,0,canvas.getWidth(), canvas.getHeight());
    Paint p = new Paint();
    p.setColor(Color.argb(255, 0, 0, 0));
    canvas.drawRect(r, p);

    
    Random rnd = new Random();
    int rx = rnd.nextInt(canvas.getWidth());
    int ry = rnd.nextInt(canvas.getHeight());
  
    int rr = rnd.nextInt(255);
    int rg = rnd.nextInt(255);
    int rb = rnd.nextInt(255);

    Rect rs = new Rect(rx,ry,rx+32,ry+32);
    Paint ps = new Paint();
    ps.setColor(Color.argb(255, rr, rg, rb));
    canvas.drawRect(rs, ps);
  }

  /**
   * Gets the example string attribute value.
   * 
   * @return The example string attribute value.
   */
  public String getExampleString() {
    return mExampleString;
  }

  /**
   * Sets the view's example string attribute value. In the example view, this
   * string is the text to draw.
   * 
   * @param exampleString
   *          The example string attribute value to use.
   */
  public void setExampleString(String exampleString) {
    mExampleString = exampleString;
    invalidateTextPaintAndMeasurements();
  }

  /**
   * Gets the example color attribute value.
   * 
   * @return The example color attribute value.
   */
  public int getExampleColor() {
    return mExampleColor;
  }

  /**
   * Sets the view's example color attribute value. In the example view, this
   * color is the font color.
   * 
   * @param exampleColor
   *          The example color attribute value to use.
   */
  public void setExampleColor(int exampleColor) {
    mExampleColor = exampleColor;
    invalidateTextPaintAndMeasurements();
  }

  /**
   * Gets the example dimension attribute value.
   * 
   * @return The example dimension attribute value.
   */
  public float getExampleDimension() {
    return mExampleDimension;
  }

  /**
   * Sets the view's example dimension attribute value. In the example view,
   * this dimension is the font size.
   * 
   * @param exampleDimension
   *          The example dimension attribute value to use.
   */
  public void setExampleDimension(float exampleDimension) {
    mExampleDimension = exampleDimension;
    invalidateTextPaintAndMeasurements();
  }

  /**
   * Gets the example drawable attribute value.
   * 
   * @return The example drawable attribute value.
   */
  public Drawable getExampleDrawable() {
    return mExampleDrawable;
  }

  /**
   * Sets the view's example drawable attribute value. In the example view, this
   * drawable is drawn above the text.
   * 
   * @param exampleDrawable
   *          The example drawable attribute value to use.
   */
  public void setExampleDrawable(Drawable exampleDrawable) {
    mExampleDrawable = exampleDrawable;
  }
}
解説
画面に図形を描画するカスタムビュークラスです。詳細はこちらの記事を参照してください。

実行結果

プロジェクトを実行します。矩形が位置を変えながらランダムに描画されます。

補足

より高速に描画する必要がある場合はSurfaceViewを用います。
著者
iPentecのプログラマー、最近はAIの積極的な活用にも取り組み中。
とっても恥ずかしがり。
掲載日: 2013-03-18
iPentec all rights reserverd.