이 튜토리얼에서는 안드로이드 앱에서 한 프래그먼트(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>위 코드에서는 화면을 상하로 분할하고, 각 영역에 FirstFragment와 SecondFragment를 배치하여 두 프래그먼트 사이에서 데이터를 주고받을 수 있도록 구성했습니다.
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)를 활용하면 더욱 간결하고 안정적으로 프래그먼트 간 통신을 구현할 수 있습니다.