ボタンをつくる -2/2- (クラスを分けて実装編)
今回の学習も「Androidの館」様のサイトの解説を元に勉強させてもらいます。
1回目はこちら
前回はActivityに直接実装していましたが、今回は専用のクラスに分離して実装するようです。
構成は、
・SampleActivity クラス(メインのクラス)
・ButtonClickListener クラス(onClickを実装するクラス)
public class SampleActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button btn = (Button)findViewById(R.id.sampleButton); btn.setOnClickListener( new ButtonClickListener(this) ); } }
「ButtonClickListener」のインスタンスを代入(引数は、Activity自身である「this」)
public class ButtonClickListener implements OnClickListener{ private Context context; // コンストラクタ ButtonClickListener(Context c){ context = c; } public void onClick(View v) { Toast.makeText( context.getApplicationContext(), "ボタンが押されました", Toast.LENGTH_LONG).show(); } }
実装されるクラスで行う
コンストラクタが受け取った「this」(の内容が格納された「context」)
のgetApplicationContext()メソッドを使う
ボタンをつくる -1/2- (簡単実装編)
今回の学習より「Androidの館」様のサイトの解説を元に勉強させてもらいます。
(2回構成)
まずは一番簡単な実装と思われる、Activity自身(SampleActivity)に実装する場合。
エディタでボタンを貼り付けて、ボタンのidは「sampleButton」という名前にしてみました。(任意でOK)
public class SampleActivity extends Activity implements OnClickListener{ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //「findViewById」を使って、レイアウトで作ったViewを探す(引数にはIDを指定) //エディタでボタンを作った際、 //Rクラスには自動的にこのボタンを識別する変数が追加されているとのこと。 //引数にはこのIDを指定。よって「R.id.sampleButton」となります。 Button btn = (Button)findViewById(R.id.sampleButton); //ボタンがクリックされたイベントを取得する為に「リスナー」を登録。 //(ボタンが押された時、「onClick」というメソッドが呼ばれる仕組みです) //このonClickというメソッドがどこにあるか知らせるため、 //Buttonクラスの setOnClickListener にonClickを実装している //クラスのインスタンスを知らせます。 //(今回はActivity自身に実装したので、「this」を渡します) btn.setOnClickListener(this); } public void onClick(View v) { Toast.makeText(this, "ボタンが押されました", Toast.LENGTH_LONG).show(); } }
【基本中の基本を学ぶ】プロジェクトの作成について
Android Studioでは、プロジェクト作成時の設定は概ねこんな感じ。
プロジェクト作成最初の画面
Application Name
アプリケーション名、と読み取れるがプロジェクト名と理解した方が良いとのこと。
ホーム画面等で表示されるアプリケーション名はstrings.xmlで設定可能なのでやはり英数字で設定すべきか。
なお、最初の1文字目は大文字が推奨らしい・・・。
例:HelloAndroid
Company Domain
アプリケーションの作成者を「ドメイン名として区別する(表現する)」。と考えれば良いのかな。
ここにドメイン名を入力する事で自動的にPackege nameを生成します。
他の人とかぶらなければ何入れてもいいのか?
例:gpz900r.type88
Package Name
「世界中のAndroidアプリケーションと区別するための名前」とのこと。
AndroidStudioでは上記の「Company Domain」を入力すると、「Application Name」と合体させて自動で生成するので、特に手を加える必要は無い。
「Target Android Devices」画面
・Phone and Tabletのみにチェックを付ける
・Minimum SDKは自分だけ使えれば良いから「Android 6.0 (Marshmallow)」にしておこう
「Add an activity to Mobile」画面
AndroidStudioではプロジェクト作成時にある程度インターフェースの出来あがっているテンプレを用意してくれているが、ここではアクションバーにメニューなどの設定も無い(一番シンプルなプロジェクト)である「Empty Activity」を選択。
「Customize the Activity」画面
とりあえずデフォルトのままでFinish。
恐らく巷の解説サイトもデフォルトの名前で作られているであろうから、よくわからんうちはむしろ触らない方がいいね。
【基本中の基本を学ぶ】プロジェクト作成時のTextViewを見てみる
これがプロジェクト作成時のactivity_main.xmlの内容
最初の「Hello world!」を表示しているTextViewのみが配置されている状態。
↓
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <TextView android:text="@string/hello_world" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </RelativeLayout>
ここの<TextView>要素中に書かれている
android:text="@string/hello_world"
により、strings.xmlの中に定義されている「hello_world」を呼び出している事が判る。
ちなみにstrings.xmlの中身はこれ
↓
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">TextView_Test</string> <string name="hello_world">Hello world!</string> <string name="action_settings">Settings</string> </resources>
上から2番目の<string>要素に対し「hello_world」という名前のname属性を与えられているが、その中にHello world!のテキストの姿が見える。これがアクティビティ上に表示されている「Hello world!」の文字の正体だ。
非同期処理がよくわかるサンプル
同期、非同期の処理について「どう動作するのか」は”なんとなく”理解していたものの、「どう実装するのか」についてはサッパリだった。
という訳でググってみた時に見つけたのが、「とほほのJava入門」の中の「スレッド」のページ。
元のサンプルはループが1000回実行されてるが、これを10回に書き換えてみた。(なんとなく直観的なような気がして)
class ThreadTest{ public static void main(String[] args){ ThreadTestThread tt = new ThreadTestThread(); tt.start(); for(int i=0;i<10;i++){ System.out.print('.'); } } } class ThreadTestThread extends Thread{ public void run(){ for(int i=0;i<10;i++){ System.out.print('@'); } } }
実行すると、「main」側で「.」を10回出力(表示)する間に、もう一つのスレッドが「@」を割り込んで出力するというデモプログラム。
上記プログラムを実行した時の結果(例)は、こんな感じ
↓
.@@@.@@@@@@@........
もちろん、スレッドの動作順序(というかタイミング)はその時々によるので(なんでかは知らん)、毎回この順番とは限らない。てか、この結果は偏り過ぎだろ。
実装方法としては、
・スレッドを生成するクラスを定義する(例では「ThreadTestThread」クラス)
このクラスは親クラスである「Thread」クラスを継承している
(教科書的な表現だと、スーパークラスの「Thread」クラスからサブクラスの「ThreadTestThread」を派生させる。みたいになるのか)
・main側で「ThreadTestThread」クラスをインスタンス化して(ttがそれ)、Threadクラスに実装されている「start」メソッドを呼ぶだけ。簡単。(startメソッドを呼ぶと、run()が実行されるらしい)
どうやら非同期処理を実現するには別の方法もあるらしいが、また今度(Threadが理解できるようになったら)試してみよう。
エントリーポイントはどこだ
Androidではmain関数ではなく、最初に起動するアクティビティが実質のエントリーポイントになるらしい。
”最初に起動”されるアクティビティを見分けるポイントは、「AndroidMainifest.xml」内のintent-filter要素に「android.intent.action.MAIN」が記述されてるものが当たりらしい。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="jp.example.yoshiyasu.drawtest01" > <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>