【Android】新規画面の追加、別画面としての扱い(Java)

最近、Android Studioを使って、JavaのAndroidアプリを独学で作成しているので、その過程で勉強した内容です。
作成したコードはGithubで公開しているので、気になる方は下記をご覧ください。
https://github.com/NagaJun1/OriginalCalendar

#新規画面作成においての前提
まず、Androidで新規画面（アプリ起動後の初期画面とは別の画面）を表示するには、Javaの場合は`setContentView();`を実行することで表示できます。
ですが、この場合、Androidのライフサイクル（`onStart()`や`onStop()`などのイベント）を使用することが難しくなります。
その問題を解消するために、`Intent`を使用した処理を実装する必要があります。

#新規画面の作成
新規画面の'.xml'作成は、プロジェクト作成時に作成される`\res\layout\activity_main.xml`と同様の作りにすればOKです。
（例として、`activity_sample.xml`としておきます。）
ついでに書いておくと、デフォルトの場合は、大枠が`<androidx.constraintlayout.widget.ConstraintLayout>`で設定されていますが、`RelativeLayout`などの別のレイアウトでも問題ありません。
例としては、下記のような書き方をします。

```xml:activity_sample.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
</RelativeLayout>
```

#画面を開く（イベントを処理する）Javaのコード
これも、プロジェクト作成時に作られる、`\MainActivity.java`と同様の作りでOKです。
（例として、`SampleActivity.java`としておきます。）
画面を読み込む処理として、`@Override`の`onCreate()`を実装しますが、このときの`setContentView()`で、先ほど作成した.xmlレイアウトを読み込みます。

```java:SampleActivity.java
import androidx.appcompat.app.AppCompatActivity;

public class SampleActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        // layoutの.xmlを指定する
        setContentView(R.layout.activity_sample);
    }
}
```

#AndroidManifest.xmlへの追加
Javaのコードで`AppCompatActivity`を継承したクラスを実装したとき、`AndroidManifest.xml`に`<activity>`として追加する必要があります。(IDEのビルド時はエラーになりませんが、処理の実行時にエラーになります。）

```xml:manifest\AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.originalcalendar">

    <application
        >
        <!-- 一部省略 -->
        <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>

        <!--下記が追加した内容-->
        <activity
            android:name=".SampleActivity"
            android:exported="true"/>
    </application>
</manifest>
```

#遷移先画面（新規画面）の呼び出し
ここで、記事の初めのほうに出てきた`Intent`の話になります。
呼び出す側のコードは下記の様になります。

```java:MainActivity.java
// 一部省略
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // ボタンを取得して、ボタン押下で画面遷移するように設定
        Button btn = findViewById(R.id.sample_button);
        btn.setOnClickListener(v -> {
            // Intent を生成
            // 第一引数はこの処理のContext
            // 第二引数に遷移先画面のSampleActivityを指定
            Intent newIntent = new Intent(btn.getContext(), SampleActivity.class);

            // Intent にデータを保存
            newIntent.putExtra("KEY1", "value");

            // 新規画面表示実行
            startActivity(newIntent);
        });
    }
```

`AppCompatActivity`を継承した、遷移先画面のクラスを含む`Intent`を生成して、`startActivity(intent);`を実行することで画面を遷移することができます。
上記のサンプルコードでは、`intent.putExtra("KEY1", "value")`が存在していますが、これは、`Intent`にデータを保持するための処理です。
遷移先の画面で`intent.getStringExtra("KEY1")`を実行することで、"value"を取得できます。
処理内容的には`Map`と同じです。

#一つ前の画面に戻る
一つ前の画面に戻る場合は、`finish()`を実行することで戻ることができます。
Androidの処理では、一つの画面が一つのタスクという認識らしいので、`finish()`を実行することで現画面の処理が終了し、前画面に戻せるということです。
つまり、画面遷移と書いていますが、実際の処理は画面を上書きしているだけということになります。
処理内部としては、画面が上書きされたタイミングで前画面の処理が停止するため、`onStop()`などの処理が実行されます。

#終わりに
今回学習した内容で、独自に作成しているアプリの処理面の問題が大きく改善できたので良かったです。
場合によっては、もっと強引な操作になっていたかもしれません（笑）

あと、全然関係ないですが、今、夜中の二時なんですが、なぜ記事を書くと夜中になってしまうのでしょう？
昼間に暇があるなら、昼間のうちに書けば良いのに.....
昼間の自分に伝えたい（笑）