Neden parçalarda varsayılan olmayan kurucuları kullanmak istemiyorum?


173

Bir uygulama oluşturuyorum Fragmentsve bunlardan birinde varsayılan olmayan bir kurucu oluşturdum ve şu uyarıyı aldım:

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

Birisi bana bunun neden iyi bir fikir olmadığını söyleyebilir mi?

Bunu nasıl başaracağımı da önerebilir misiniz?

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

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

Varsayılan olmayan yapıcıyı kullanmadan?



3
Hayır, yardım etmiyorlar. Soruma cevap vermediler. Ama teşekkür ederim hiçbiri daha az :)
BlackHatSamurai

31
@BlaineOmega Aslında bu özellikle: stackoverflow.com/a/11602478/321697 sorunuzu kesinlikle yanıtlıyor. Parçanın yeniden oluşturulmasına neden olan bir yönlendirme değişikliğinde veya başka bir olayda Android, varsayılan yapıcıyı ve bağımsız değişken olarak iletilen Paketi kullanır. Özel bir kurucu kullanıyorsanız, bu olaylardan biri nedeniyle parça yeniden oluşturulur oluşturulmaz, özel kurucuda yaptığınız her şey kaybolur.
Kevin Coppock

1
Teşekkürler, ama bu nedenini cevaplıyor, ama nasıl değil.
BlackHatSamurai

Bu, orijinal yorumumdaki birinci ve ikinci bağlantılar tarafından kapsanmaktadır.
CommonsWare

Yanıtlar:


110

Bir paket nesnesi oluşturun ve verilerinizi ekleyin (bu örnekte Categorynesneniz). Dikkatli olun, serileştirilemezse bu nesneyi doğrudan pakete geçiremezsiniz. Bence nesnenizi parçanın içine inşa etmek ve pakete sadece bir kimlik veya başka bir şey koymak daha iyidir. Bu, bir paket oluşturmak ve eklemek için kullanılan koddur:

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

Bundan sonra, parça erişim verilerinizde:

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

Bu kadar.


3
nasıl bir nesne geçmek? Bir Bağlam Nesnesi veya başka bir nesne geçmek istiyorum.
Adil Malik

12
Paketler, nesnelerin yanı sıra serileştirilmiş Java nesnelerini de taşıyabilir Parcelable. Ayrıca, a'ya geçmemelisiniz Context, çünkü bu bilgilere parçanın getActivity()yöntemi ile erişilebilir .
krakatoa

Parça olarak bunu nerede yapmalı Type value = getArguments().getType("key");?
Muhammed Babar

4
@Muhammad Babar: Ben olsaydım, metoda eklerdim newInstance(). Örneğin: public static FragmentName newInstance(your variables){}. Android belgelerinin önerdiği gibi, parametrelerle bir kurucu yapmayın, çünkü varsayılan (parçasız) parçanızın yeniden başlatılmasından sonra otomatik olarak çağrılır.
nistv4n

@MuhammadBabar onCreateView tamam
chanjianyi

272

Yanıtların hiçbiri "neden varsayılan olmayan kuruculardan ziyade parametreleri iletmek için paket kullanmalı?"

Parametreleri paketten geçirmenizin nedeni, sistem bir geri yüklendiğinde fragment(örn. Yapılandırma değişikliğinde), otomatik olarak geri yüklenecektir bundle.

Parametreleri aşağıdaki gibi beğenmeli onCreateveya onCreateViewokumalıdır bundle- bu şekilde fragmentdoğru durumunu durumunu fragmentbaşlatıldığı duruma geri yüklemeniz garanti edilir (bu durumun onSaveInstanceState bundleiletilen durumdan farklı olabileceğini unutmayın onCreate/onCreateView)

Statik newInstance()yöntemi kullanma önerisi sadece bir öneridir. Varsayılan olmayan bir kurucu kullanabilirsiniz, ancak o kurucunun bundlegövdesinin içindeki başlatma parametrelerini doldurduğunuzdan emin olun . Ve bu parametreleri onCreate()veya onCreateView()yöntemlerinde okuyun.


2
İyi açıkladı. Teşekkürler. Soruyu soran olsaydım, sana bir kene
verirdim

5
Artık varsayılan olmayan yapıcıyı kullanamazsınız (herhangi bir nedenle) .... derleyici hatası verir (uyarı olarak kullanılır).
MPavlak

51

Bunu Fragmentnasıl FragmentManagersomutlaştırdığı için kuruculara sahip olmamalısınız . İhtiyacınız newInstance()olan parametrelerle tanımlanmış statik bir yönteme sahip olmanız, daha sonra bunları paketlemeniz ve daha sonra Bundleparametreyle erişebileceğiniz parçanın argümanları olarak ayarlamanız gerekir .

Örneğin:

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 ;
}

Ve şu argümanları okuyun onCreate:

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

    //...
}

Bu şekilde, ayrılır ve yeniden eklenirse, nesne durumu, s'ye bundlesekli gibi, bağımsız değişkenler aracılığıyla saklanabilir Intent.


9

Bir sınıf için parametre kullanırsanız. bunu dene

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

5
Bu aslında kötü bir öneri. Parça a tarafından yeniden oluşturulduğunda FragmentManager, mSomeInstance kaybedersiniz.
Yaroslav Mytkalyk

Kabul edildi, SomeClass, setArguments () kullanılarak ayrıştırılabilir ve bir pakette saklanmalıdır
Jake_

1

Bence, statik kurucu ile iki kurucu (argümanları bir Fragment argümanları paketine depolayan boş ve parametrelenmiş) arasında bir fark yoktur, büyük olasılıkla, bu başparmak kuralı Java'da arg argümanı yapmayı unutma olasılığını azaltmak için yaratılmıştır. aşırı yüklenme olduğunda örtük olarak üretilmez.

Projelerimde Kotlin kullanıyorum ve bunları sadece bir pakete depolayan ve onu Fragment argümanları olarak ayarlayan argümanlar için birincil no-arg yapıcısı ve ikincil kurucu ile parçalar uyguluyorum.


0

Parça yapılandırmadan sonra varsayılan olmayan kurucular kullanıyorsa parça değiştirilirse tüm veriler kaybedilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.