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

액티비티에서 프래그먼트에 값을줄때 게터세터를 사용하면 안되나요 ?

0 추천
public class MainActivity extends AppCompatActivity {


    int y = 0;
    int m = 0;
    int d = 0;
    long now = System.currentTimeMillis();
    Date date = new Date(now);
    SimpleDateFormat sdfYear = new SimpleDateFormat("yyyy");
    SimpleDateFormat sdfMonth = new SimpleDateFormat("MM");
    SimpleDateFormat sdfday = new SimpleDateFormat("dd");
    SimpleDateFormat sdfDate = new SimpleDateFormat("yyyyMMdd");
    String nowYear = sdfYear.format(date);
    String nowMonth = sdfMonth.format(date);
    String nowDay = sdfday.format(date);
    String nowDate = sdfDate.format(date);

    ShareData shareData = new ShareData();
    ImageButton wallpaperButton;

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


        shareData.setDate(nowDate);


        BottomNavigationView navView = findViewById(R.id.nav_view);
        AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
                R.id.navigation_fragment1, R.id.navigation_fragment2, R.id.navigation_fragment3)
                .build();
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
        NavigationUI.setupWithNavController(navView, navController);





        wallpaperButton = findViewById(R.id.button_wallpaper);
        wallpaperButton.bringToFront();
        wallpaperButton.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                wallpaperload();
            }
        });


    }

제 애플리케이션은 실행하면 간단히 메인액티비티가 실행됨과 동시에 프래그먼트에서 리사이클러뷰를 띄워주는 방식인데 문제는 메인액티비에서 프래그먼트로 초기값을 넘겨주고싶어서 getter/setter 나 Bundle로 값을 넘겨주려고했지만 초기값이 프래그먼트로 전달되지않습니다. 일주일동안 생명주기를 다시 공부하고 삽질해봤는데 제가모르는부분인지 원인을 찾을수가 없더라구요.. 메인액티비티에서 버튼을 클릭할때마다 프래그먼트로 값을 넘겨줘서 그때마다 프래그먼트를 갱신해 값을 바꾸는식의 어플을 만들려고했는데 생각처럼 되질않네요... 

 

제가 알고싶은점은 저처럼 앱실행과 동시에 메인액티비티에서 프래그먼트를 띄워주었을때 메인액티비티에서 프래그먼트에 초기값을 어떻게 넘겨주는지 알고싶습니다.

 

아래는 프래그먼트쪽 소스와 게터세터 클래스 필요한 부분만 첨부합니다.

public class Fragment1 extends Fragment {

    private RecyclerAdapter adpater;
    private RecyclerView mRecyclerView;
    private RecyclerView.LayoutManager mLayoutManager;
    ShareData shareData = new ShareData();
    
    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_fragment1, container, false);

        mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
        mRecyclerView.setHasFixedSize(true);
        mLayoutManager = new LinearLayoutManager(getActivity());
        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.scrollToPosition(0);
        adpater = new RecyclerAdapter();
        mRecyclerView.setAdapter(adpater);

        
        listLoad(); //이쪽은 Asynk task로 데이터를 긁어와 어댑터에 연결해서 리사이클러뷰에 뿌려주는 함수입니다. 


        return view;


}

 

게터세터부문

public class ShareData {

    private String date;

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }
}

 

rladbghks13 (150 포인트) 님이 2021년 11월 6일 질문

1개의 답변

0 추천
 
채택된 답변

결론적으로 올바른 방법이 아닙니다. 이유는 라이프 사이클 때문에 그런데, 대표적으로 디바이스가 회전할 때 프레그먼트는 다시 생성이 되어 이전에 있던 상태를 복구하게 됩니다. 당연히 setter를 통해 설정했던 값은 초기화가 됩니다. 이 때문에 프레그먼트를 호출할 때, setArguments(https://developer.android.com/reference/androidx/fragment/app/Fragment.html#setArguments(android.os.Bundle) 를 통해 필요한 값을 넘기도록 설계가 되어 있습니다. arguments를 통해 전달된 값이 디바이스 회전같은 상황이 되면 안드로이드 시스템이 값을 저장했다가 프레그먼트가 다시 생성될 때 복구를 해줍니다. 하지만  setter를 통해서 설정된 값은 이게 되지 않습니다. 액티비티도 비슷합니다.  Intent를 통해 전달하는 것이 맞습니다. 액티비티나 프레그먼트를 일반 클래스처럼 다룰 수 없는 이유이기도 하구요. arguments 나 intent  를 통해 전달되는 클래스는 원시타입이거나 Serializable이나 Parcelable를 구현한 클래스여야 합니다.

 액티비티에서 프레그먼트를 생성할 때 초기값을 넘기는 방법은, 아래처럼 프레그먼트의 setArgument에 Bundle를 설정해주면 됩니다. 

Fragment1 fragment = new Fragment1();
Bundle bundle = new Bundle();
bunlde.putExtra("키값",  {넘기고 싶은데이터});
fragment.setArguments(bundle);


이 값을 프레그먼트에 읽을 때는, 넘긴 데이터 타입에 따라 Bundle에 있는 아래와 같은 형태의 메소드를 호출하시면 됩니다.

getArguments.getX("키값", 기본값)

https://developer.android.com/reference/androidx/fragment/app/Fragment.html#getArguments()
https://developer.android.com/reference/android/os/Bundle.html



그리고 프레그먼트에 접근하는 방법은 fragmentManager.findFragmentBy를 통해 프레그먼트를 구해서 접근하거나 아니면 데이트를 가진 인스턴스(ViewModel, Repository, Storgage 등등) 를 공유하는 방법입니다. 님의 경우는 ViewModel + LiveData를 액티비티와 프레그먼트 간에 공유하면 쉽게 해결이 될 것 같아 보이네요.

spark (227,470 포인트) 님이 2021년 11월 6일 답변
rladbghks13님이 2021년 11월 11일 채택됨
...