タイトル: アクティビティ間のパラメータの受け渡し
SEOタイトル: Android Activity 間パラメータ受け渡し完全ガイド
| この記事の要点 |
|
基本: Intent.putExtra
Android で Activity 間に値を渡すもっとも基本の方法。Intent に extras(キー値ペア)として詰めて起動先で取り出します。
Java
// 送信側
Intent intent = new Intent(this, DetailActivity.class);
intent.putExtra("USER_ID", 42);
intent.putExtra("USER_NAME", "Yamada");
intent.putExtra("IS_VIP", true);
startActivity(intent);
// 受信側 (DetailActivity)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
int userId = intent.getIntExtra("USER_ID", -1);
String name = intent.getStringExtra("USER_NAME");
boolean vip = intent.getBooleanExtra("IS_VIP", false);
}
Kotlin
// 送信側
val intent = Intent(this, DetailActivity::class.java).apply {
putExtra("USER_ID", 42)
putExtra("USER_NAME", "Yamada")
putExtra("IS_VIP", true)
}
startActivity(intent)
// 受信側
val userId = intent.getIntExtra("USER_ID", -1)
val name = intent.getStringExtra("USER_NAME")
val vip = intent.getBooleanExtra("IS_VIP", false)
定数化(推奨)
class DetailActivity : AppCompatActivity() {
companion object {
private const val EXTRA_USER_ID = "USER_ID"
private const val EXTRA_USER_NAME = "USER_NAME"
fun newIntent(ctx: Context, userId: Int, name: String): Intent =
Intent(ctx, DetailActivity::class.java).apply {
putExtra(EXTRA_USER_ID, userId)
putExtra(EXTRA_USER_NAME, name)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val userId = intent.getIntExtra(EXTRA_USER_ID, -1)
val name = intent.getStringExtra(EXTRA_USER_NAME) ?: ""
}
}
// 呼び出し
startActivity(DetailActivity.newIntent(this, 42, "Yamada"))
キー名のタイポ防止 + 入出力 API がわかりやすくなる定石。
オブジェクトを渡す: Parcelable
カスタムクラスを渡すには Parcelable 実装が必要。Kotlin なら @Parcelize で自動生成:
// build.gradle (Module)
// plugins { id 'kotlin-parcelize' }
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
data class User(
val id: Int,
val name: String,
val email: String,
) : Parcelable
// 送信
val user = User(1, "Yamada", "y@example.com")
val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("USER", user)
startActivity(intent)
// 受信
val user: User? = intent.getParcelableExtra("USER")
// API 33+ では型を明示
val user: User? = intent.getParcelableExtra("USER", User::class.java)
Serializable は使うな(基本)
Serializable はリフレクションを使うため Parcelable より遅く、推奨されません。古いコードでよく見る:
// ❌ 非推奨(パフォーマンス劣る)
data class User(val id: Int, val name: String) : Serializable
// ✅ 推奨
@Parcelize
data class User(val id: Int, val name: String) : Parcelable
Bundle で複数値を一括
val bundle = Bundle().apply {
putInt("USER_ID", 42)
putString("USER_NAME", "Yamada")
putParcelable("USER", user)
}
val intent = Intent(this, DetailActivity::class.java)
intent.putExtras(bundle)
startActivity(intent)
// 受信
val bundle = intent.extras ?: Bundle()
val userId = bundle.getInt("USER_ID")
結果を受け取る: 旧 startActivityForResult は非推奨
Android 11 (API 30) で startActivityForResult は非推奨になり、Jetpack の Activity Result API が標準です:
// ❌ 旧: 非推奨
override fun onActivityResult(reqCode: Int, resCode: Int, data: Intent?) {
if (reqCode == 100 && resCode == RESULT_OK) {
val value = data?.getStringExtra("RESULT")
}
}
// ✅ 新: registerForActivityResult
class MainActivity : AppCompatActivity() {
private val pickEditor = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == RESULT_OK) {
val value = result.data?.getStringExtra("RESULT")
}
}
private fun openEditor() {
val intent = Intent(this, EditorActivity::class.java)
pickEditor.launch(intent)
}
}
// EditorActivity 側
fun finishWith(value: String) {
val data = Intent().apply { putExtra("RESULT", value) }
setResult(RESULT_OK, data)
finish()
}
定義済み Contract
// 画像選択
val pickImage = registerForActivityResult(
ActivityResultContracts.GetContent()
) { uri: Uri? -> /* ... */ }
pickImage.launch("image/*")
// 写真撮影
val takePicture = registerForActivityResult(
ActivityResultContracts.TakePicture()
) { success: Boolean -> /* ... */ }
// 権限要求
val requestPermission = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { granted: Boolean -> /* ... */ }
requestPermission.launch(Manifest.permission.CAMERA)
Navigation Component + Safe Args(モダン)
Single Activity + Fragment 構成の現代 Android 標準。型安全に引数を渡せます:
// 送信側: Safe Args で生成された Direction クラスを使用
val action = ListFragmentDirections.actionListToDetail(userId = 42, user = user)
findNavController().navigate(action)
// 受信側: navArgs() で型安全に取得
class DetailFragment : Fragment() {
private val args: DetailFragmentArgs by navArgs()
override fun onViewCreated(view: View, saved: Bundle?) {
val userId = args.userId
val user = args.user
}
}
ViewModel + SavedStateHandle
大きなオブジェクトや UI 状態は Intent ではなく ViewModel で保持し、SavedStateHandle で OS kill にも備える:
class DetailViewModel(private val state: SavedStateHandle) : ViewModel() {
val userId: Int = state["userId"] ?: -1
val userName: String = state["userName"] ?: ""
fun updateName(name: String) {
state["userName"] = name
}
}
// 起動側で nav args / Intent extras 経由で渡す
class DetailActivity : AppCompatActivity() {
val vm: DetailViewModel by viewModels()
}
Jetpack Compose での Argument
NavHost(navController, startDestination = "list") {
composable("list") { ListScreen(navController) }
composable(
"detail/{userId}",
arguments = listOf(navArgument("userId") { type = NavType.IntType })
) { backStack ->
val userId = backStack.arguments?.getInt("userId") ?: -1
DetailScreen(userId)
}
}
// 遷移
navController.navigate("detail/42")
永続的に値を保持したい場合
| 用途 | 推奨 |
|---|---|
| 軽い設定値 | SharedPreferences / DataStore (推奨) |
| 構造化データ | Room (SQLite ラッパ) |
| セキュアな情報 | EncryptedSharedPreferences |
| セッション中のみ | Application class の field / Singleton |
注意点
- Intent に大きなオブジェクト(巨大画像/数 MB の Bitmap)を入れると
TransactionTooLargeException - 渡せる総量は約 1 MB。大きいデータは ViewModel / DB / ファイル経由
- Process Death(OS によるプロセス kill)対策に SavedStateHandle / onSaveInstanceState を活用
- API 33+ の
getParcelableExtraは型指定オーバーロードを推奨
FAQ
Q: 多数の引数を渡したい
A: data class を作って Parcelable 化 → 1 つの extra で渡すのがクリーンです。
Q: 巨大画像を渡したい
A: Intent ではなく URI(content://)を渡し、受信側で BitmapFactory.decodeStream。または ViewModel / Repository 経由。
Q: Fragment 間ならどう渡す?
A: Safe Args、または setFragmentResult / setFragmentResultListener(Fragment Result API)。