Androidタイマーを思い出そう。

変更履歴

これはなに?

 去年やったAndroidでタイマーを使ってみるやつのリメイク。ちょっとおまけつき。

これは何をどう動作するプログラムですか?

起動して一秒後に「1匹のほむほむ」と表示されます。あとは2秒ごとに2匹、3匹と増えていきます。 意味?適当に決まっとる。繰り返すがキニスンナ XD

Resources/layout/main.xml

で、リメイクなので中身も変わらない。
まずは表示空間をレイアウトで指定。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView
    android:id="@+id/textView1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Hello World, MainActivity"
    />
</LinearLayout>

MainActivity.java

次に変態、もとい本体。

Javaではタイマーがスレッドになっているという面倒くさい仕掛けになっている。解はいくつかあると思うが、僕は以下のようにした。

というもの。

ただし、上記のタイマー的動作は独立稼働してしまうので、プログラム終了を検知したら停止するようにした。これが sunset と書いてあるフラグで、 true→日没ってことで、これを検出したらこちらも終了(finish)する。

うん、これ以上なくシンプルですよね XD

唯一の注意点は、「○匹のほむほむ」という間抜けなメッセージ。わざとソースに注釈残してあるのだけど、改めて書こう。

たかが「ほむほむ」、されど「ほむほむ」。入門していた時、ここでひっかかってひどい目にあっちまった。
で、対策は以下のようにした。

こうしてやると、そのonCreateから呼びだされたスレッドの中でも画面上のリソースに書き込めるみたいだ。

うむ、何か勉強になったような気がしないでもないぞ。

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity
{
    private boolean sunset = false; // trueになったら日没(プログラム終了)。
    private int count = 0;
    private final Context context = this;
    private final Handler handler = new Handler();
    //private TextView web = (TextView) findViewById(R.id.textView1); // ←ここで直接セットするとAndroidで例外になるぞ! onCreateでやれ
    private TextView web;
    private final Runnable showMessageTask = new Runnable() {
        @Override
        public void run() {
            if(sunset == false){
                web.setText(String.valueOf(++count) + "匹のほむほむ");
                handler.removeCallbacks(showMessageTask); // 自分自身を再呼び出しする前にコールバックを消しておこう。
                handler.postDelayed(showMessageTask, 2000);
            }else{ // fin.
                finish();
            }
        }
    };
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        web = (TextView) findViewById(R.id.textView1);
        handler.postDelayed(showMessageTask, 1000);
    }

    @Override
    public void onBackPressed() {
        new AlertDialog.Builder(MainActivity.this).setPositiveButton("終了",
                new DialogInterface.OnClickListener() {
            public void onClick(
                    DialogInterface dialog,
                    int which) {
                try {
                    count = -9999;
                    sunset = true;
                } catch (Error e) {
                }
                MainActivity.this.finish();
            }
        }).setNegativeButton("Cancel", null).setMessage("終了しますか??").show();
    }
}

manifest

さて。ここまででちゃんと動くけど、端末をくるくる回してみよう。値がリセットされちゃいますよね?

そんなわけで、縦固定にしましょう。manifestでやります。

<activity android:name="MainActivity"
                  android:label="@string/app_name"
                  android:screenOrientation="portrait">

これで縦固定になります。ちなみに値は以下のような感じらしい。

ふむ、わかりやすい。