[ Do it! ] 안드로이드 앱 프로그래밍 - #3. 어플리케이션 구성하기 (1)

ma.caron_g·2022년 3월 2일
0

Do it! - Android Studio

목록 보기
7/18
post-thumbnail

[ 어플리케이션 구성 ]

안드로이드는 화면 배치를 알려주는 .xml 파일과 화면 기능을 담당하는 .java 파일로 분리되어 있습니다.
하나의 화면을 만들 때는 xml레이아웃 파일과 java 소스 파일 하나를 쌍으로 만들어야합니다.
이때 xml 레이아웃 파일이 java 소스 파일과 매칭시키는 명령어는 setContentView()입니다.

[ MainActivity.java ]

기본 자바 소스파일의 기본 정보를 살펴보면
onCreate 메서드 안에 setContentView를 이용하여 기본 xml 레이아웃 파일 이름을 파라미터로 전달되면 xml 레이아웃 자바 소스 코드가 서로 연결됩니다.

이때 R.layout.activity_main.xml 이라는 코드에 Rres폴더를 가리킵니다.

package com.study.doit;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

}

화면의 기능을 담당하는 자바 소스 파일을 하나 만들면 그 안에는 AppCompatActivity를 상속하는 하나의 클래스가 자동 생성됩니다.
이 클래스가 상속하는 AppCompatActivity에는 화면에 필요한 기능들이 들어있습니다.

[ 인플레이션 이해하기 ]

앱을 실행하면 xml에 있는 코드 내용들이 화면에 출력되게 됩니다.

xml 레이아웃 코드를 자바 소스 코드에서 사용하려면 앱이 실행될 때 xml 코드 내용이 메모리로 로딩되어 객체화되어 화면에 출력하는데 이 과정을 인플레이션(Inflation)이라고 합니다.

인플레이션 과정은 앱을 만드는 과정에서 매우 중요합니다.
왜냐하면 xml 레이아웃 파일은 앱이 실행되는 시점에 로드되어 메모리에 객체화되기 때문입니다.

이를 실험하기 위해,
setContentView(R.layout.레이아웃명)(인플레이션)을 호출하기 전에 코드를 선언하면 어떻게 되는지 확인해보겠습니다.

[ setContentView() ]

package com.study.doit;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;


public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Button btnId;

        btnId = findViewById(R.id.btnId);
        btnId.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(getApplicationContext(), "누르지마라", Toast.LENGTH_SHORT).show();
            }
        });
        setContentView(R.layout.activity_main);

    }

}

인플레이션이 되기 전에 뷰를 연결하여 onClick 이벤트를 실행해보려 하겠습니다.

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener<android.view.View$OnClickListener>' on a null object reference at com.study.doit.MainActivity.onCreate< MainActivity.java:21>

위와 같은 오류가 발생합니다.

아직 레이아웃과 뷰를 생성하지 않았기 때문인데

이를 통해 setContent(R.layout.레이아웃명) 메서드를 이용하여

  • 화면에 나타낼 뷰를 지정하는 역할
  • 레이아웃의 내용을 메모리에 객체화하는 역할



[ getSystemService() ]

레이아웃 전체를 표현하는 것이 아닌 일부분만 표현할 수 있습니다.

이를 위해 안드로이드는 LayoutInflater라는 클래스를 제공합니다.
이 클래스는 시스템 서비스로 제공되므로 다음과 같은 코드를 이용하여 LayoutInflater객체를 참조 후 사용 가능합니다.

getSystemService(Context.LAYOUT_INFLATER_SERVICE)

시스템 서비스는 단말이 시작되면 항상 실행되는 서비스입니다.

[ 부모 레이아웃.xml ]

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:layout_margin="10dp"
    tools:context=".PartActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="버튼을 눌러 화면을 추가하세요"
        android:textSize="20sp"/>
    <Button
        android:id="@+id/btnAdd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="추 가"
        android:textSize="20sp"
        android:textStyle="bold"/>
    <LinearLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

    </LinearLayout>

</LinearLayout>

[ 부분 레이아웃.xml ]

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#C1ADF1">

    <TextView
        android:id="@+id/txtView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="부분 화면1"
        android:textSize="30sp"
        android:textStyle="bold"/>

    <CheckBox
        android:id="@+id/chkBox"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="동의합니다."/>

</LinearLayout>

[ 부모 레이아웃.java ]

package com.study.doit;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.LinearLayout;

public class PartActivity extends AppCompatActivity {

    LinearLayout container;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_part);

        container = (LinearLayout) findViewById(R.id.container);

        Button btnAdd = (Button) findViewById(R.id.btnAdd);

        btnAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                inflater.inflate(R.layout.activity_sample, container, true);

                //객체화 시켜 인플레이션 했으므로 부분 레이아웃의 뷰를 사용 가능.
                CheckBox checkBox = container.findViewById(R.id.chkBox);
                checkBox.setText("로딩되었어요.");
            }
        });
    }
}

위에 사진을 보면 메인 화면이 MainActivity (activity_main.xml)가 아닌
activity_part.xml로 코딩이 돼 있으며 그 화면을 메인 화면으로 띄웠다.


그 방법은
app/manifests/AndroidManifest.xml에서 값을 기본 인텐트값을 바꿔주면 가능합니다.

android:name=""기본 설정값이 아래와 같이 돼 있을텐데

<activity
    android:name=".PartActivity"
    android:exported="false" />
<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=".MainActivity"
    android:exported="false" />
<activity
    android:name=".PartActivity"
    android:exported="true">
    <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
profile
다른 사람이 만든 것을 소비하는 활동보다, 내가 생산적인 활동을 하는 시간이 더 많도록 생활화 하자.

0개의 댓글