왜 프래그먼트에서 기본이 아닌 생성자를 피하고 싶습니까?


173

나는 Fragments그들 중 하나를 사용하여 앱을 만들고 있는데, 기본 생성자가 아닌 생성자를 만들고이 경고를 받았습니다.

Avoid non-default constructors in fragments: use a default constructor plus Fragment#setArguments(Bundle) instead

왜 이것이 좋은 생각이 아닌지 말해 줄 수 있습니까?

내가 어떻게 이것을 할 것인지 제안 할 수 있습니까?

public static class MenuFragment extends ListFragment {
    public ListView listView1;
    Categories category;

    //this is my "non-default" constructor
    public MenuFragment(Categories category){
        this.category = category;
    }....

기본이 아닌 생성자를 사용하지 않습니까?



3
아니요, 도움이되지 않습니다. 그들은 내 질문에 대답하지 않았다. 그러나 적은 : 당신에게 전혀 감사하지
BlackHatSamurai

31
@BlaineOmega 사실 이것은 특히 : stackoverflow.com/a/11602478/321697은 확실히 귀하의 질문에 대답합니다. 방향 변경 또는 조각을 다시 만드는 기타 이벤트에서 Android는 기본 생성자와 인수로 전달 된 번들을 사용합니다. 커스텀 생성자를 사용하는 경우, 이러한 이벤트 중 하나로 인해 조각이 재생성되면 커스텀 생성자에서 수행 한 모든 작업이 손실됩니다.
Kevin Coppock

1
고마워하지만 그 이유에 대한 대답이지만 방법은 아닙니다.
BlackHatSamurai

그것은 내 원래 의견의 첫 번째와 두 번째 링크로 덮여 있습니다.
CommonsWare

답변:


110

번들 오브젝트를 작성하고 데이터 (이 예제에서는 Category오브젝트)를 삽입하십시오 . 직렬화 가능하지 않으면이 오브젝트를 번들로 직접 전달할 수 없습니다. 조각으로 객체를 작성하고 번들에 id 또는 다른 것을 넣는 것이 좋습니다. 다음은 번들을 만들고 첨부하는 코드입니다.

Bundle args = new Bundle();
args.putLong("key", value);
yourFragment.setArguments(args);

그 후, 조각 액세스 데이터에서 :

Type value = getArguments().getType("key");

그게 다야.


3
객체를 전달하는 방법? 컨텍스트 객체 또는 다른 객체를 전달하고 싶습니다.
Adil Malik

12
번들은 객체뿐만 아니라 직렬화 된 Java 객체를 전달할 수 있습니다 Parcelable. 또한 Context조각의 getActivity()메소드 를 통해 정보에 액세스 할 수 있으므로를 전달해서는 안됩니다 .
krakatoa

조각이 어디에서 이것을 Type value = getArguments().getType("key");해야합니까?
Muhammad Babar

4
@ Muhammad Babar : 내가 당신이라면 newInstance()방법에 추가 할 것 입니다. 예를 들면 다음과 같습니다 public static FragmentName newInstance(your variables){}.. Android 설명서에서 권장하는 것처럼 조각을 다시 시작한 후 기본 매개 변수 (매개 변수 없음)가 자동으로 호출되므로 매개 변수를 사용하여 생성자를 만들지 마십시오.
nistv4n

@MuhammadBabar onCreateView은 OK입니다
chanjianyi

272

실제로 "기본이 아닌 생성자가 아닌 매개 변수를 전달하기 위해 번들을 사용하는 이유"에 대한 답변은 없습니다.

번들을 통해 매개 변수를 전달해야하는 이유는 시스템이 fragment(예 : 구성 변경시) 복원 할 때 자동으로을 복원하기 때문 bundle입니다.

콜백 은 매개 변수를 읽 onCreate거나 onCreateView읽어야합니다. bundle이 방법 으로 초기화 된 fragment것과 동일한 상태로 올바르게 상태를 복원 fragment할 수 있습니다 (이 상태 onSaveInstanceState bundle는에 전달 된 것과 다를 수 있습니다 onCreate/onCreateView)

정적 newInstance()방법 을 사용 하는 것이 좋습니다. 기본 생성자가 아닌 생성자를 사용할 수 있지만 bundle해당 생성자의 본문 내부 에서 초기화 매개 변수를 채워야합니다 . onCreate()또는 onCreateView()메소드 에서 해당 매개 변수를 읽으십시오 .


2
잘 설명했다. 감사. 내가 질문을 한 사람이라면 진드기를 줄 것입니다.
Karue Benson Karue

5
더 이상 기본이 아닌 생성자를 사용할 수 없습니다 (어떤 이유로 든) .... 컴파일러 오류가 발생합니다 (경고로 사용됨).
MPavlak

51

당신 Fragment때문에 방법의 생성자가 없어야 FragmentManager을 인스턴스화합니다. newInstance()필요한 매개 변수 로 정적 메서드를 정의한 다음 번들로 묶어 조각의 인수로 설정하면 나중에 Bundle매개 변수로 액세스 할 수 있습니다 .

예를 들면 다음과 같습니다.

public static MyFragment newInstance(int title, String message) {
    MyFragment fragment = new MyFragment();
    Bundle bundle = new Bundle(2);
    bundle.putInt(EXTRA_TITLE, title);
    bundle.putString(EXTRA_MESSAGE, message);
    fragment.setArguments(bundle);
    return fragment ;
}

다음에서이 인수를 읽으십시오 onCreate.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    title = getArguments().getInt(EXTRA_TITLE);
    message = getArguments().getString(EXTRA_MESSAGE);

    //...
}

이런 식으로 분리하고 다시 연결하면 객체 상태는 s에 bundles첨부 된 것처럼 인수를 통해 저장할 수 있습니다 Intent.


9

일부 클래스에 매개 변수를 사용하는 경우 이 시도

SomeClass mSomeInstance;
public static final MyFragment newInstance(SomeClass someInstance){
    MyFragment f = new MyFragment();
    f.mSomeInstance = someInstance;
    return f;
}

5
이것은 실제로 나쁜 제안입니다. 에 의해 Fragment가 다시 생성되면 FragmentManagermSomeInstance가 손실됩니다.
Yaroslav Mytkalyk

합의, SomeClass는 소포 가능하고 setArguments ()를 사용하여 번들로 저장되어야합니다.
Jake_

1

나는 정적 생성자와 두 생성자 (Fragment의 arguments 번들에 인수를 저장하는 비어 있고 매개 변수가있는 생성자) 사이에 차이가 없다고 생각합니다. 아마도이 엄지 손가락 규칙은 Java에서 인수가없는 생성자를 구현하는 것을 잊어 버릴 가능성을 줄이기 위해 만들어졌습니다. 과부하가있을 때 암시 적으로 생성되지 않습니다.

내 프로젝트에서 Kotlin을 사용하고 인수로 기본 no-arg 생성자와 보조 생성자를 사용하여 조각을 구현하여 번들에 저장하고 Fragment 인수로 설정하면 모든 것이 잘 작동합니다.


0

구성 변경 후 프래그먼트가 기본이 아닌 생성자를 사용하면 프래그먼트가 모든 데이터를 잃게됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.