これはなに?
- Androidで画面遷移するための知識整理・Tips
- IntentとActivityによる起動のみです
- 公式サイトもある程度参照してます
- Fragmentとかの話はまた別途...
- こちらの本の第7章「画面遷移とIntentクラス」の内容を自分なりに整理した内容となります。
- (+α) 起動ロジックは呼び出される側においた方が良くね?という話
目次
Androidの画面遷移は"遷移"ではない
- WebアプリとかだとURLによるルーティングやリダイレクトがあって別画面に「遷移する」けど、Androidだとそうでは無い
- 元画面の上に別画面が生成されて「載る」形になる。
- 元画面に戻る際は、「載っている画面を消す」形になる。
新画面作るのに必要なもの・手順
layout用xml
- 画面構成を定義する
- AndroidStudioでビジュアライズ可能
- さまざまな部品を組み合わせる
- レイアウト構造の定義:LineraLayout,ConstraintLayout...
- その他部品:TextView,Button,ListView,etc...
- 一例として、以下は単純なリストを表示するだけのxml
activity_new.xml
<?xml version="1.0" encoding="utf-8"?> <ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/simpleList" android:layout_width="match_parent" android:layout_height="match_parent"/>
Activityクラス
- 画面を呼び出すにあたって様々な処理を書くクラス
アクティビティの概要 | Android デベロッパー | Android Developers
アクティビティにより、アプリが UI を描画するウィンドウが用意されます。通常、このウィンドウは画面全体に表示されますが、画面よりも小さく、他のウィンドウの上に重なることもあります。
NewActivity.kt
import androidx.appcompat.app.AppCompatActivity class NewActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_new) //作成済みのxmlを呼び出す // 以下詳細処理記載...
AndroidManifest.xml
- Activityクラスを作ったら、AndroidManifest.xmlに追加が必要。
- 追加しないと起動時エラー
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.sample.mysample"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.IntentSample"> <!--★★ここに新規アクティビティを追加--> <activity android:name=".NewActivity"></activity> <!--遷移元アクティビティ--> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Intent
一般的なインテント | Android デベロッパー | Android Developers
インテントを使用すると、実行したい簡単なアクション(「地図を表示する」、「写真を撮る」など)を Intent オブジェクトに記述することによって、別のアプリでアクティビティを開始できます。
インテントとインテント フィルタ | Android デベロッパー | Android Developers
Activity はアプリ内の 1 つの画面を表しています。Activity の新しいインスタンスを開始するには、Intent を startActivity() に渡します。Intent には、開始するアクティビティが記述され、必要なデータがすべて含まれています。
- startActivity(intent: Intent)を実行することで、別画面を表示することが可能
- 指定方法には明示的なものと暗黙的なものがある
- Intent自体はActivity以外(Serviceとか)も起動する
val newIntent = Intent(this@MainActivity, NewActivity::class.java) startActivity(newIntent) //これ以降NewActivityにより画面遷移開始
起動ロジックは呼び出される側に閉じた方がいいと思う
Activityの起動処理は起動されるActivityで実装すべし - Qiita
上記記事を読んで「確かに」と思ったのでメモ。クラス設計的な話。
教則本に載ってるパターン
- 画面遷移先固有のロジックを「呼び出す側」クラスに書いている
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 略 // 画面遷移先固有のロジックを「呼び出す側」クラスに書いている if (画面遷移トリガーがあったら) { val extra = "NewActivity起動に必要な情報" val newIntent = Intent(this@MainActivity, NewActivity::class.java) newIntent.putExtra("extra", extra) startActivity(newIntent) } }
class NewActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_new) } }
実務だとこうした方が便利だと思う
- 画面遷移先固有のロジックを「呼び出される側」クラスに書いている
- companionObject(javaでいうstatic)使って、クラス外から利用できるようにしておく
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 略 // 呼び出すだけ if (画面遷移トリガーがあったら) { NewActivity.start(this@MainActivity, "NewActivity起動に必要な情報") } } }
class NewActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_new) // 略 } // 呼び出される側で自身の起動ロジックを持っておく companion object { private const val EXTRA_KEY = "EXTRA_KEY" fun start(context: Context, extraValue: String) { context.startActivity( Intent(context, NewActivity::class.java).also { it.putExtra(EXTRA_KEY, extraKey) } ) } } }
メリット
- startActivty時の固有ロジックを呼び出し側で意識しなくて良くなる
- 必要な情報を渡してstartするだけでOK
- 例だと引数をそのまま渡すだけだから簡単だが、引数が多くなったり文字列を加工したりする必要が出てきた場合、こちらの方が幸せなはず。