Android Fragment onAttach () kullanımdan kaldırıldı


326

Uygulamamı en son destek kitaplığını (sürüm 23.0.0) kullanacak şekilde güncelledim, Fragment sınıfının onAttach () işlevini kullanımdan kaldırdıklarını öğrendim.

Onun yerine:

onAttach (Activity activity)

Kar:

onAttach (Context context)

Uygulamam, kullanımdan kaldırılmadan önce geçirilen etkinliği kullandığından, olası bir çözüm olduğunu düşünüyorum:

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    activity = getActivity();
}

Bunu yapmanın doğru yolu olur mu?

GÜNCELLEME:

API 23'ten daha düşük bir cihaz çalıştırırsam, yeni onAttach () bile çağrılmaz. Umarım yapmak istedikleri şey bu değildir!

GÜNCELLEME 2:

SDK'daki en son güncellemelerle ilgili sorun çözüldü.

API 22 cihazımda test yaptım ve onAttach (Context) çağrılıyor.

Birkaç hafta önce açtığım hata raporunu ve Google'daki adamların cevaplarını takip etmek için burayı tıklayın .


Başarılı örneğinizden belirli Etkinlik yöntemleri kullanıyorsanız, içeriği Etkinliklerinize aktarmayı denediniz mi? Unutmayın Etkinlik bir Bağlam alt sınıfıdır. Belki bir döküm işe yarayabilir.
MarkSkayff

nedense, onAttach () çağrılmıyor bile! herhangi bir fikir? en son destek kitaplığına güncellemeyi denediniz mi?
TareK Khoury

2
API neden taşındı Context? Bir ihtiyaç yok Activityzaten bir parça takmak ve görüntülemek için? ContextParametreyi başka nasıl kullanacaksınız ?
Kenny Worden

1
Bir hata olarak gönderdim, bkz. Link code.google.com/p/android/issues/detail?id=183358
TareK Khoury

6
Yeni onAttach(Context context)çağrılabilmesi için ya en azından API 23'e sahip bir cihaz kullanmanız VEYA android.support.v4.app.Fragment kullanmanız gerekir. Buraya
nevzo

Yanıtlar:


337

Etkinlik bir bağlamdır, bu nedenle bağlamın bir Etkinlik olup olmadığını kontrol edebilir ve gerekirse yayınlayabilirsiniz.

@Override
public void onAttach(Context context) {
    super.onAttach(context);

    Activity a;

    if (context instanceof Activity){
        a=(Activity) context;
    }

}

Güncelleme: Bazıları yeni Contextgeçersiz kılmanın hiçbir zaman çağrılmadığını iddia ediyor . Bazı testler yaptım ve bunun doğru olduğu bir senaryo bulamıyorum ve kaynak koduna göre, asla doğru olmamalı. Test ettiğim tüm durumlarda, hem SDK23 öncesi hem de sonrası, hem sürümleri hem Activityde Contextsürümleri onAttachçağrıldı. Durumun böyle olmadığı bir senaryo bulabilirseniz, sorunu gösteren örnek bir proje oluşturmanızı ve Android ekibine bildirmenizi öneririm .

Güncelleme 2: Hatalar daha hızlı giderildiği için yalnızca Android Destek Kitaplığı parçalarını kullanıyorum. Geçersiz kılmaların doğru şekilde çağrılmadığı yukarıdaki sorun, sadece çerçeve parçalarını kullanırsanız ortaya çıkar.


5
OnAttach'ın bağlam ile onAttach ile aynı şekilde çağrılmaması nedeniyle gerçek bir çözüm değil. OnAttach uygulamasında parametre olarak bir etkinliğe sahip başlatma kodunuz varsa bu değişiklik çalışmaz.
Buddy

2
Hayır, en azından benim durumumda aynı işe yaramıyor. OnAttach'ta etkinlik veya bağlam kullanmıyorum, başlatma işlemini yapıyorum. OnAttach'ı etkinlikle bağlamla değiştirmeyi denedim ve aynı şekilde çağrılmıyor. Bu yüzden kolayca değiştirilemezler.
Buddy

7
Buddy'nin sahip olduğu aynı konular ... onAttach(Context)bile denmiyor.
Stéphane

2
Kodumu adım attı ve çağrılamam mümkün olduğunu doğrulayabilirsiniz onAttach(context).
Chad Bingham

2
Benim durumumda, daha önce sistem tarafından temizlenen etkinliği yeniden başlatırsak onAttach () çağrılmaz. Ama her zaman böyle değil. OnAttach (Bağlam bağlamı), refActivity = yeni WeakReference <> ((AppCompatActivity) bağlamı) içinde bir WeakReference başlatması koydum. Ve onCreateView () zaman zaman NullPointerException atar.
Kimi Chiu

45

Bu Google'da ... önerilen değişiklik diğerine büyük bir değişikliktir: değiştirmek onAttach(Activity activity)ile onAttach(Context context)beri eski API'ler benim uygulamalar çöktü onAttach(Context context)yerli parçaların çağrıda edilmeyecektir.

Yerel parçaları (android.app.Fragment) kullanıyorum, bu yüzden eski API'larda (<23) tekrar çalışması için aşağıdakileri yapmak zorunda kaldım.

İşte yaptığım şey:

@Override
public void onAttach(Context context) {
    super.onAttach(context);

    // Code here
}

@SuppressWarnings("deprecation")
@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        // Code here
    }
}

Mr.Yoann Hercouet, u API 23 üzerinde nasıl yapılacağını açıklayabilir miyim, lütfen bana yardım edin, şimdiden teşekkürler, E / Android android.support.v4.app.FragmentManagerImpl.execSingleAction adresindeki support.v4.app.FragmentManagerImpl.moveToState. Burada u benim hata bilmek olacak gerekli satırları gönderdi.
MohanRaj S

@MohanRajS Kod parçanıza göre API 24'te (kullandığım) aynıdır, sorununuz bununla bir şey yapmak zorunda görünmemektedir.
Yoann Hercouet

@ YoannHercouet, Cevabınız için teşekkür ederim, kontrol edip güncelleyeyim.
MohanRaj S

1
Eski API'leri hedeflemede zorluk nedeniyle Google'dan memnun değilsiniz. Örneğin, eski API'leri hedefleyebileceğiniz nimetleri düşünün, örneğin Apple, sadece sizi muazzam bir şekilde sakatlayacak ve sizi yalnızca en yeni olanları desteklemeye zorlayacaktır.
Stan

39

Çerçeve parçalarını kullanırsanız ve cihazın SDK sürümü 23'ten düşükse OnAttach(Context context)çağrılmaz.

Bunun yerine destek parçaları kullanıyorum, bu nedenle kullanımdan kaldırma düzeltildi ve onAttach(Context context)her zaman çağrılıyor.


11

Şu anda onAttachParça kodundan, Contextşu anki etkinliğin olup olmadığı net değil : Kaynak Kodu

public void onAttach(Context context) {
    mCalled = true;
    final Activity hostActivity = mHost == null ? null : mHost.getActivity();
    if (hostActivity != null) {
        mCalled = false;
        onAttach(hostActivity);
    }
}

Eğer bir göz atacaksanız getActivityaynı çağrıyı göreceksiniz

/**
 * Return the Activity this fragment is currently associated with.
 */
final public Activity getActivity() {
    return mHost == null ? null : mHost.getActivity();
}

Yani emin Etkinlik daha sonra kullanmak aldığınızdan olmak istiyorsanız getActivity()(içinde onAttachde sizin Fragment) ancak kontrol etmeyi unutmayın nullçünkü eğer mHostolduğunu nulletkinlik olacaknull


6
@Override
public void onAttach(Context context) {
    super.onAttach(context);

    Activity activity = context instanceof Activity ? (Activity) context : null;
}

5

Çoğu durumda olması yeterli gibi görünse de onAttach(Context), çağrılmadığı bazı telefonlar (yani: Xiaomi Redme Note 2) vardır, bu nedenle NullPointerExceptions'a neden olur. Güvenli tarafta olmak için, kullanımdan kaldırılmış yöntemi de bırakmanızı öneririm:

// onAttach(Activity) is necessary in some Xiaomi phones
@SuppressWarnings("deprecation")
@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    _onAttach(activity);
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    _onAttach(context);
}

private void _onAttach(Context context) {
    // do your real stuff here
}

3

SDK yöneticisi ile en yeni Destek kütüphanesini indirin ve

compile 'com.android.support:appcompat-v7:23.1.1'

gradle.app ve derleme sürümünü api 23 olarak ayarlayın


1

Aşağıdaki cevap, Android geliştirici web sitesindeki Parçalar eğitiminde meydana gelen bu kullanımdan çıkarma uyarısıyla ilgilidir ve yukarıdaki yayınlarla ilgili olmayabilir.

Bu kodu eğitim dersinde kullandım ve işe yaradı.

public void onAttach(Context context){
    super.onAttach(context);

    Activity activity = getActivity();

Etkinliklerin belgelerin belirttiği gibi geçersiz olabileceğinden endişelendim.

getActivity

FragmentActivity getActivity () Bu parçanın şu anda ilişkilendirilmiş olduğu FragmentActivity'yi döndürün. Parça bunun yerine bir Bağlam ile ilişkilendirilmişse null değerini döndürebilir.

Ancak main_activity üzerindeki onCreate, parçanın yüklendiğini açıkça gösterir ve bu yöntemden sonra, fragmandan get etkinliğini çağırmak main_activity sınıfını döndürür.

getSupportFragmentManager (). beginTransaction () .add (R.id.fragment_container, firstFragment) .commit ();

Umarım bu konuda haklıyım. Ben mutlak bir acemiyim.


1

muhtemelen kullanıyorsunuz android.support.v4.app.Fragment. Bunun yerine onAttachyöntem yerine , parçanın ilişkili olduğu öğeyi getActivity()almak için kullanın FragmentActivity. Yoksa onAttach(Context context)yöntemi kullanabilirsiniz .


0

Kullanıcı tanımlanmış Arayüz 'TopSectionListener', nesne aktivite komutanı olduğunda bu benim için çalıştı:

  //This method gets called whenever we attach fragment to the activity
@Override
public void onAttach(Context context) {
    super.onAttach(context);
    Activity a=getActivity();
    try {
        if(context instanceof Activity)
           this.activitycommander=(TopSectionListener)a;
    }catch (ClassCastException e){
        throw new ClassCastException(a.toString());}

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