Computer >> 컴퓨터 >  >> 프로그래밍 >> Android

안드로이드에서 프래그먼트 간 데이터 전달하는 방법 – 인터페이스 콜백 활용 가이드

이 튜토리얼에서는 안드로이드 앱에서 한 프래그먼트(Fragment)에서 다른 프래그먼트로 데이터를 전달하는 방법을 단계별로 알아봅니다. 두 프래그먼트가 직접 통신하는 것은 권장되지 않기 때문에, 일반적으로 액티비티(Activity)를 중재자로 활용한 인터페이스 콜백 방식을 사용합니다. 아래 예제를 통해 첫 번째 프래그먼트의 버튼을 클릭하면 해당 메시지가 두 번째 프래그먼트로 전달되어 화면에 표시되는 과정을 확인할 수 있습니다.

1단계: 새 프로젝트 생성

Android Studio를 열고 File → New Project로 이동한 후, 필요한 모든 세부 정보를 입력하여 새 프로젝트를 생성합니다.

2단계: activity_main.xml 레이아웃 작성

res/layout/activity_main.xml 파일에 다음 코드를 추가합니다.

<?xml version = "1.0" encoding = "utf-8"?>
<LinearLayout xmlns:android = "https://schemas.android.com/apk/res/android"
    android:orientation = "vertical"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent">
    <LinearLayout
        android:id = "@+id/linearlayout01"
        android:layout_width = "fill_parent"
        android:layout_height = "fill_parent"
        android:background = "#ccc"
        android:layout_weight = "1"
        android:orientation = "vertical">
        <fragment android:name = "com.example.myapplication.FirstFragment"
            android:id = "@+id/frag_1"
            android:layout_width = "fill_parent"
            android:layout_height = "fill_parent" />
    </LinearLayout>
    <LinearLayout
        android:id = "@+id/linearlayout02"
        android:layout_width = "fill_parent"
        android:layout_height = "fill_parent"
        android:layout_weight = "1"
        android:background = "#eee"
        android:orientation = "vertical">
        <fragment android:name = "com.example.myapplication.SecondFragment"
            android:id = "@+id/frag_2"
            android:layout_width = "fill_parent"
            android:layout_height = "fill_parent" />
    </LinearLayout>
</LinearLayout>

위 코드에서는 화면을 상하로 분할하고, 각 영역에 FirstFragmentSecondFragment를 배치하여 두 프래그먼트 사이에서 데이터를 주고받을 수 있도록 구성했습니다.

3단계: MainActivity.java 작성

src/MainActivity.java 파일에 다음 코드를 추가합니다.

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity implements OnButtonPressListener {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    @Override
    public void onButtonPressed(String msg) {
        SecondFragment Obj = (SecondFragment) getSupportFragmentManager().findFragmentById(R.id.frag_2);
        Obj.onFragmentInteraction(msg);
    }
}

여기서 핵심은 MainActivity가 OnButtonPressListener 인터페이스를 구현한다는 점입니다. 첫 번째 프래그먼트에서 버튼 클릭 이벤트가 발생하면 액티비티의 onButtonPressed() 메서드가 호출되고, 액티비티는 ID를 통해 두 번째 프래그먼트를 찾아 메시지를 전달합니다.

4단계: FirstFragment.java 작성

src/FirstFragment.java 파일에 다음 코드를 추가합니다.

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class FirstFragment extends Fragment{
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
        ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment, null);
        init(root);
        return root;
    }
    OnButtonPressListener buttonListener;
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            buttonListener = (OnButtonPressListener) getActivity();
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement onButtonPressed");
        }
    }
    void init(ViewGroup root) {
        TextView but = (TextView)root.findViewById(R.id.text);
        but.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                buttonListener.onButtonPressed("Message From First Fragment");
            }
        });
    }
}

첫 번째 프래그먼트는 onAttach() 시점에 호스트 액티비티가 리스너 인터페이스를 구현했는지 검증합니다. 만약 구현하지 않았다면 ClassCastException을 발생시켜 개발 단계에서 오류를 즉시 파악할 수 있도록 합니다. TextView를 클릭하면 onButtonPressed()를 호출하여 메시지를 액티비티로 전송합니다.

5단계: SecondFragment.java 작성

src/SecondFragment.java 파일에 다음 코드를 추가합니다.

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class SecondFragment extends Fragment {
    TextView textView;
    View view;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.fragment, container, false);
        return view;
    }
    public void onFragmentInteraction(String uri) {
        Log.d("sai",uri);
        textView = view.findViewById(R.id.text);
        textView.setText(uri);
    }
}

두 번째 프래그먼트는 액티비티로부터 onFragmentInteraction() 메서드를 통해 메시지를 받으면, 로그캣(Logcat)에 기록하고 화면의 TextView에 해당 내용을 출력합니다.

6단계: fragment.xml 레이아웃 작성

res/layout/fragment.xml 파일에 다음 코드를 추가합니다. 이 레이아웃은 두 프래그먼트에서 공통으로 사용됩니다.

<?xml version = "1.0" encoding = "utf-8"?>
<LinearLayout
    xmlns:android = "https://schemas.android.com/apk/res/android"
    android:layout_width = "match_parent"
    android:gravity = "center"
    android:layout_height = "match_parent">
    <TextView
        android:id = "@+id/text"
        android:textSize = "30sp"
        android:text = "Click"
        android:layout_width = "wrap_content"
        android:layout_height = "wrap_content" />
</LinearLayout>

7단계: OnButtonPressListener 인터페이스 작성

src/OnButtonPressListener.java 파일에 다음 코드를 추가합니다.

public interface OnButtonPressListener {
    public void onButtonPressed(String msg);
}

이 인터페이스가 프래그먼트와 액티비티 사이의 통신 계약 역할을 수행합니다. 프래그먼트는 인터페이스만 알고 있으며, 실제 구현체(액티비티)에 의존하지 않으므로 결합도가 낮아지고 재사용성이 높아집니다.

앱 실행 및 결과 확인

이제 애플리케이션을 실행해 보겠습니다. 실제 안드로이드 기기를 컴퓨터에 연결했다고 가정합니다. Android Studio에서 프로젝트의 액티비티 파일 중 하나를 연 뒤, 툴바의 Run(실행) 아이콘을 클릭하세요. 목록에서 본인의 모바일 기기를 선택하면 앱이 설치되고 기본 화면이 표시됩니다.

안드로이드에서 프래그먼트 간 데이터 전달하는 방법 – 인터페이스 콜백 활용 가이드

첫 번째 프래그먼트의 TextView를 클릭하면, 아래 화면과 같이 전달된 메시지가 두 번째 프래그먼트에 표시되는 것을 확인할 수 있습니다.

안드로이드에서 프래그먼트 간 데이터 전달하는 방법 – 인터페이스 콜백 활용 가이드

마무리 정리

프래그먼트 간 직접 참조는 컴포넌트의 생명주기 문제로 오류를 유발할 수 있습니다. 따라서 이 예제처럼 인터페이스 콜백 + 액티비티 중재 패턴을 사용하는 것이 안전합니다. 참고로 최신 안드로이드 개발에서는 Jetpack의 ViewModel 공유 또는 Fragment Result API(setFragmentResultListener)를 활용하면 더욱 간결하고 안정적으로 프래그먼트 간 통신을 구현할 수 있습니다.