마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

Fragment result api를 이용한 프래그먼트간 데이터 전달

0 추천

프래그먼트간 데이터전달에 result API를 이용하는 방법이 있다는것을 발견하고 시도하는데

잘안돼서 질문드립니다.

앱설명을 드리자면 싱글 액티비티로 도전중입니다.

메인화면(액티비티)가 바텀내비게이션으로 이루어져 있습니다. 3개의 메뉴가 있고 그중 1개 메뉴(프래그먼트)만 만들어놓은상태입니다.

 

메뉴 이동후 바뀐 화면에서 버튼을누르면 다이얼로그프래그먼트 창이 뜹니다.

여기서 데이터를 선택후 창을 닫으면, 창 종료와 함께 선택한 데이터를 전달하면서

또 다른 프래그먼트로 전환하게끔 하는것이 목표입니다.

 

데이터를 전달 없이 창 종료후 프래그먼트 전환 테스트에서는 잘 됐는데

데이터를 전달하기 시작하고부터 자꾸 앱이 튕기네요.

전환한 프래그먼트에서 전달된 데이터가 null이라고 뜨는게 문제입니다..

 

하지만 왜 그런지 잘모르겠습니다. 디버깅결과 전달하기까지는 Bundle에 데이터가 들어가있는것을 확인했습

니다. 아마 받는쪽에서 null이 되는것 같습니다.

 

창 종료후 화면전환은 액티비티에서 전환 메소드를 구현해서 프래그먼트에서 호출하는 방식으로 햇습니다.

무엇이 문제일까요.. 화면을 전환하는 과정(액티비티의 전환메소드를 호출할때)에서 데이터를 셋팅하는게

문제인것같은데 잘 캐치를 못하겠습니다..무엇이 문제일까요..

 

 

* result API라는 프래그먼트간 데이터 전달하는 것이 문서에 나와있어서 사용해보고 있는데 너무 복잡한 방법이라면,, 혹은 비추천한다면 말씀해주세요

 

MainActivity.java

public class MainActivity extends AppCompatActivity {
    BottomNavigationView bottomNav;
    FragmentManager fm;
    FragmentTransaction transaction;
    Fragment curFrag;

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

        bottomNav = findViewById(R.id.bottom_nav);

        bottomNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                fm = getSupportFragmentManager();
                transaction = fm.beginTransaction();
                curFrag = fm.getPrimaryNavigationFragment();
                String tag = String.valueOf(item.getItemId());
                int id = item.getItemId();

                if(curFrag != null) {
                    transaction.hide(curFrag);
                }

                Fragment fragment = fm.findFragmentByTag(tag);
                if(fragment == null) { // 일단 메뉴 하나만 구현
                    if(id == R.id.list)
                        fragment = new WorkoutListFragment();
                    transaction.add(R.id.content_layout, fragment);
                }
                else {
                    transaction.show(fragment);
                }

                transaction.setPrimaryNavigationFragment(fragment);
                transaction.setReorderingAllowed(true);
                transaction.commitNow();
                return true;
            }
        });
    }

    public void onFragmentChanged() {
        transaction = fm.beginTransaction();
        String tag = "WriteRoutine";

        curFrag = fm.getPrimaryNavigationFragment();
        if (curFrag != null) {
            transaction.hide(curFrag);
        }

        Fragment fragment = fm.findFragmentByTag(tag);
        if (fragment == null) {
            fragment = new WriteRoutineFragment();
            transaction.add(R.id.content_layout, fragment, tag);
        } else {
            transaction.show(fragment);
        }

        transaction.setReorderingAllowed(true);
        transaction.commitNow();
    }
}

 

BodyPartDialogFragment.java

public class BodyPartDialogFragment extends DialogFragment {

    Button startBtn;
    ArrayList<String> bodypart_strData; // 선택된 부위 보낼 문자열 인스턴스
    String[] dialog_str_list;
    int selectedNum; // 선택된 부위 개수

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_body_part_dialog, null);

        // 추 가 (저장일지 추가)
        startBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(selectedNum == 0){ // 하나도 선택되지 않았을때
                    Toast.makeText(getContext(), "부위를 선택해 주세요", Toast.LENGTH_SHORT).show();
                }
                else {
                    MainActivity activity = (MainActivity) getActivity();
                    Bundle result = new Bundle();
                    result.putStringArrayList("title", bodypart_strData);
                    getParentFragmentManager().setFragmentResult("result", result);
                    activity.onFragmentChanged();

                    dismiss();
                }
            }
        });

        return view;
    }
}

 

WriteRoutineFragment.java

public class WriteRoutineFragment extends Fragment {
    TextView title;
 
    List<String> titleData;


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getParentFragmentManager().setFragmentResultListener("result", this, new FragmentResultListener(){
            @Override
            public void onFragmentResult(@NonNull String requestKey, @NonNull Bundle result) {
                if(result != null)
                    titleData = result.getStringArrayList("title");
            }
        });
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.activity_write_routine, container, false);

        initViews(rootView);
        setPageTitle();
        
        return rootView;
    }

    public void setPageTitle() {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            String new_title = String.join(" / ", titleData);
            title.setText(new_title);
        }
        else {
            StringBuilder new_title = new StringBuilder();
            for (int i = 0; i < titleData.size(); i++) {
                if (i == titleData.size() - 1) {
                    new_title.append(titleData.get(i));
                    break;
                }
                new_title.append(titleData.get(i)).append(" / ");
            }
            title.setText(new_title);
        }

    }
}

 

 

codeslave (3,940 포인트) 님이 2021년 4월 6일 질문
codeslave님이 2021년 4월 6일 수정

1개의 답변

0 추천
해당 API를 아직 안써봐서 확실하지는 않는데, ResultAPI를 프레그먼트 간에 사용하실 때는 백스택에 프레그먼트가 추가되어 있어야 하는 것으로 보이네요. 프레그먼트를 추가할 때 FragmentTransaction 에 addToBackStack() 부분이 없으면 백스택에 추가가 안된상태입니다.
spark (226,420 포인트) 님이 2021년 4월 6일 답변
...