Activity
Overview
this vs. getApplicationContext
様々な API に Context インターフェイスを渡すことがある。
Activity は Context を継承しているため、アクティビティ自身の this
を渡しても動作するが、getApplicationContext
との使い分けを意識する必要がある。
this
は、アクティビティのライフサイクルと連動するgetApplicationContext
は、アプリケーションのライフサイクルと連動する
単に Context として、アクティビティ自身 this
を渡すと、受け側のAPIが Context の参照を保持していた場合、アクティビティのライフサイクルで破棄されず、メモリリークを起こしてしまう。かといって、メモリリークを避けるために、一律で getApplicationContext
を使うべきかというとそうではない。
registerReceiver
で BroadcastReceiver を登録するシナリオを考えてみると、アクティビティから登録されたレシーバは、明示的に unregisterReceiver
を行なわなかった場合でも、アクティビティのライフサイクルで破棄されるが、アプリケーションから登録された場合は、明示的に破棄しなければ、いつまでもレシーバは待機しつづけることになる。
onPause vs. onStop
アクティビティはバックグラウンドに移る際 onPause
が呼ばれ休止状態に入る。他のアプリケーションによりメモリが不足した場合 onStop
が呼ばれずにアプリケーションが終了する場合がある。このため、SharedPreference などの永続化処理は onPause
で行なう必要がある。
しかし HONEYCOMB 以降からは、アプリケーションのプロセスが終了する前には onStop
が呼ばれることが保証されている。
Starting with Honeycomb, an application is not in the killable state until its onStop() has returned.
このため、HONEYCOMB 以降のみのサポートであれば、永続化処理は onStop
で行えばよい。onPause
は、次のアプリケーションのためにリソースを使うため、このタイミングでコストのかかる処理は好ましくない。
Cheat Sheet
Starting another activity
Intent intent = new Intent(this, AnotherActivity.class);
startActivity(intent);
Starting another activity from the chooser
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, "foo");
intent.setType("text/plain")
Intent chooser = Intent.createChooser(intent, "Share this text via");
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(chooser);
}
Receiving an activity result
private final static int REQUEST_CODE_FOO = 1;
private void startAnotherActivity() {
Intent intent = new Intent(this, AnotherActivity.class);
startActivityForResult(intent, RESULT_CODE_FOO);
}
...
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_FOO) {
if (resultCode == RESULT_OK) {
String txt = data.getStringExtra(Intent.EXTRA_TEXT);
...
}
}
}
AnotherActivity.class
:
private void done() {
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_TEXT, "foo");
setResult(RESULT_OK, intent);
finish();
}
Adding an OnClickListener
You can set the android:onClick
attribute to the method name of the activity having the corresponding view.
<Button
...
android:onClick="doSomething" />
public void doSomething(View view) {
....
}
However, if the method name is missing, it causes a runtime error. For more type safety, you would rather use the View#setOnClickListner
method manually.
import android.view.View;
import android.view.View.OnClickListener;
...
Button button = (Button) findViewById(R.id.button_send);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
doSomething();
}
});
Retrieving all activities for the intent
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
...
Intent httpScheme = new Intent(Intent.ACTION_VIEW, Uri.parse("http://example.net"));
PackageManager packageManager = getPackageManager();
List<ResolveInfo> activities = packageManager.queryIntentActivities(httpScheme, 0);