반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 받은 트랙백

글 보관함

[CookBook] Fragments 이해하기 -7-

2013. 9. 29. 16:47 | Posted by 솔웅


Implementing Communication Between Fragments



fragment들 사이에서 데이터를 전달할 수 있도록 하기 위해 Fragment 클래스에서는 두개의 메소드를 제공하고 있습니다. 바로 setArguments() 와 getArguments() 인데요. setArguments() 메소드는 fragment의 Bundle을 저장합니다. getArguments() 메소드는 이 전달된 정보를 얻기 위해 Bundle을 retrieve 하죠.



아래 코드는 fragment1에서 fragment2로 정보를 전달합니다. frag2_container는 layout xml 에서 지정한 fragment container의 ID 입니다.



#1 Fragment2Activity fragment2 = new Fragment2Activity();
#2 Bundle args = new Bundle();
#3 String message = "Message from Fragment1";
#4    if(null==fragmentManager.findFragmentByTag(TAG2)){
#5        Fragment2Activity fragment2 = new Fragment2Activity();
#6      args.putString("msg", message);
#7      fragment2.setArguments(args);
#8      fragmentTransaction.replace(R.id.frag2_container,fragment2);
#9        String tag = null;
#10        fragmentTransaction.addToBackStack(tag);
#11        fragmentTransaction.commit();
#12 }



#1에 있는 Fragment2Activity는 fragment2의 자바 클래스를 말합니다. fragment2라는 자바 클래스 인스턴스를 생성했습니다.
#2에서는 args라고 하는 Bundle 객체를 생성했습니다.
#3에서는 message라고 하는 String 객체를 생성했죠. 이 메세지는 fragment2에 전달 될 겁니다.
#4번에서는 TAG2라는 fragment가 있는지 여부를 체크합니다. TAG2는 fragment2를 말하는 거니까 fragment2가 있는지 여부를 체크하는 겁니다.
#5번은 Fragment2Activity 자바클래스의 인스턴스를 만들고 #6번에서는 args 번들에 3번에서 정의했던 메세지를 세팅합니다.
#7에서는 fragment2에 이 Bundle 을 세팅하구요.
#8번과 #9번에서는 이전의 fragment를 navigating하는 부분이구요.



이 activity stack은 이전의 activity들을 계속 track 합니다. Back 버튼을 누르면 activity stack에 있는 activity가 pop up 되서 그 activity 가 화면에 보여지게 됩니다. 다른 말로 이 activity stack은 Back 버튼을 누르면 이전 화면으로 돌아갈 수 있도록 만드는 거죠.



fragment도 이러한 개념을 사용합니다. back stack에 FragmentTransaction을 추가하려면 commit() 하기 전에 FragmentTransaction의 addToBackStack() 메소드를 호출해야 합니다.



위 코드에서 보면 처음에는 xml에 있는 fragment가 화면에 보였다가 두번째 fragment로 replace됐습니다. 그리고 이전 fragment는 BackStack에 넣구요. 그래서 Back 버튼을 누르면 이전의 FragmentTransaction이 돌아와서 이전의 fragment가 화면에 보여질 겁니다.



Bundle을 통해서 위에 setArguments()메세지를 통해 세팅된 정보를 어떻게 다음 fragment에서 이 메세지를 받고 display하는지에 대해서도 궁금할 겁니다. 그 답은 Bundle을 사용해서 fragment에서 메세지를 받는 것은 getArgument() 메소드를 사용한다 입니다.
아래에 샘플 코드가 있습니다.



String messageReceived = "";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    ViewGroup container, Bundle savedInstanceState) {
        Bundle bundle = getArguments();
        if(bundle != null) {
            messageReceived = bundle.getString("msg");
        }
    }
}


fragment끼리의 communication을 이해하기 위해 FragmentsByCodeApp 어플리케이션에서 fragment1에서 fragment 2로 메세지를 보내는 것을 구현하겠습니다. 이를 위해 FragmentsByCodeAppActivity.java 의 코드를 수정합니다.



public class FragmentsByCodeAppActivity extends Activity implements OnOptionSelectedListener {
    private static final String TAG1 = "1";
    private static final String TAG2 = "2";
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragments_by_code_app);
        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        if(null==fragmentManager.findFragmentByTag(TAG1)){
            Fragment1Activity fragment1 = new Fragment1Activity();
            fragmentTransaction.add(R.id.frag1_container, fragment1, TAG1); 
        }
        Bundle args = new Bundle();
        String message="Message from Fragment 1";  

        if(null==fragmentManager.findFragmentByTag(TAG2)){
            Fragment2Activity fragment2 = new Fragment2Activity();
            args.putString("msg", message);
            fragment2.setArguments(args);

            fragmentTransaction.add(R.id.frag2_container, fragment2, TAG2); 
        }
        fragmentTransaction.commit();
        }

    public void onOptionSelected(String msg){
        Fragment2Activity frag2 = (Fragment2Activity) getFragmentManager().findFragmentById(R.id.frag2_container);
        frag2.dispOption(msg);             
    }
}



우선 Bundle 인스턴스인 args를 생성했습니다. 이 args 객체에 message라는 String 객체를 put 했구요. 그리고 이 Bundle을 fragment2에 넣었습니다. 그 다음에 fragment2에서는 이 Bundle 을 getArguments() 메소드를 이용해서 이 정보를 받습니다. 그 받는 부분을 한번 보겠습니다.



public class Fragment2Activity extends Fragment {
    TextView selectedOpt;
    String messageReceived="";


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View vw= inflater.inflate(R.layout.fragment2,  container, false);
           Bundle bundle=getArguments(); 
           if(bundle !=null) {
               messageReceived = bundle.getString("msg");
               selectedOpt = (TextView) vw.findViewById(R.id.selectedopt);
               selectedOpt.setText(messageReceived);
           }
           return vw;     

    }

    public void dispOption(String msg){
        TextView selectedOpt = (TextView) getActivity().findViewById(R.id.selectedopt);
        selectedOpt.setText("You have selected "+msg);  
    }
}


이렇게 getArguments()를 사용해서 해당 정보를 받습니다. 이렇게 받은 정보는 TextView에 뿌려질 거구요.



이 어플리케이션을 실행하면 아래와 같은 화면을 볼 수 있습니다.






Fragment base 클래스 이외에도 fragment는 다른 몇개의 Fragment 클래스의 subclass들을 extend 할 수 있습니다. DialogFragment, ListFragment, PreferenceFragment들이 그것입니다.

반응형

Comment