Android Fragment onAttach () sudah usang


326

Saya telah memperbarui aplikasi saya untuk menggunakan pustaka dukungan terbaru (versi 23.0.0), saya menemukan bahwa mereka mencabut fungsi onAttach () dari kelas Fragment.

Dari pada:

onAttach (Activity activity)

Bersalju:

onAttach (Context context)

Karena aplikasi saya menggunakan aktivitas yang diteruskan sebelum penghentian, solusi yang mungkin menurut saya adalah:

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

Apakah itu cara yang benar untuk melakukannya?

MEMPERBARUI:

Jika saya menjalankan perangkat dengan API lebih rendah dari 23, onAttach () baru bahkan tidak dipanggil. Saya harap ini bukan yang ingin mereka lakukan!

PEMBARUAN 2:

Masalah telah diselesaikan dengan pembaruan terbaru ke SDK.

Saya telah menguji pada perangkat API 22 saya dan onAttach (Konteks) dipanggil.

Klik di sini untuk mengikuti laporan bug yang saya buka beberapa minggu yang lalu dan jawaban dari orang-orang di Google.


Jika Anda menggunakan metode Aktivitas spesifik dari instance yang Anda lewati, pernahkah Anda mencoba menampilkan konteks ke aktivitas Anda? Ingat Kegiatan adalah subkelas Konteks. Mungkin casting akan berhasil.
MarkSkayff

untuk beberapa alasan, onAttach () bahkan tidak dipanggil! ada ide? apakah Anda mencoba memperbarui ke lib dukungan terbaru.?
TareK Khoury

2
Mengapa API dipindahkan Context? Tidakkah Anda memerlukan sebuah Activityuntuk melampirkan dan menampilkan sebuah fragmen? Bagaimana lagi Anda menggunakan Contextparameter?
Kenny Worden

1
Saya telah diposting sebagai bug, lihat link code.google.com/p/android/issues/detail?id=183358
Tarek Khoury

6
Agar onAttach(Context context)dapat dipanggil, Anda harus menggunakan perangkat yang memiliki setidaknya API 23 ATAU menggunakan android.support.v4.app.Fragment. Lihat di sini
nevzo

Jawaban:


337

Aktivitas adalah konteks, jadi jika Anda bisa mengecek konteksnya adalah sebuah Aktivitas dan melemparkannya jika perlu.

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

    Activity a;

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

}

Pembaruan: Beberapa mengklaim bahwa Contextpenggantian baru tidak pernah dipanggil. Saya telah melakukan beberapa tes dan tidak dapat menemukan skenario di mana ini benar dan menurut kode sumber, seharusnya tidak pernah benar. Dalam semua kasus yang saya diuji, baik pra dan pasca SDK23, baik Activitydan Contextversi onAttachdipanggil. Jika Anda dapat menemukan skenario di mana ini bukan masalahnya, saya sarankan Anda membuat proyek sampel yang menggambarkan masalah dan melaporkannya ke tim Android .

Pembaruan 2: Saya hanya pernah menggunakan fragmen Perpustakaan Dukungan Android karena bug diperbaiki lebih cepat di sana. Tampaknya masalah di atas di mana penggantian tidak dipanggil dengan benar hanya terungkap jika Anda menggunakan fragmen kerangka kerja.


5
Bukan solusi karena onAttach dengan konteks tidak disebut dengan cara yang sama seperti onAttach with activity. Jika Anda memiliki beberapa kode inisialisasi di onAttach dengan aktivitas sebagai parameter, perubahan ini tidak akan berfungsi.
Buddy

2
Tidak, itu tidak berfungsi sama, setidaknya dalam kasus saya. Saya tidak menggunakan aktivitas atau konteks di onAttach, saya melakukan inisialisasi. Saya sudah mencoba mengganti onAttach dengan aktivitas ke konteks dengan dan itu tidak dipanggil dengan cara yang sama. Jadi mereka tidak mudah dipertukarkan.
Buddy

7
Masalah yang sama yang dimiliki Buddy ... onAttach(Context)bahkan tampaknya tidak dipanggil.
Stéphane

2
Saya telah melangkah melalui kode saya dan saya dapat memverifikasi bahwa mungkin untuk onAttach(context)tidak dipanggil.
Chad Bingham

2
Dalam kasus saya, onAttach () tidak akan dipanggil jika kita memulai kembali aktivitas yang dihapus oleh sistem sebelumnya. Tapi tidak selalu seperti ini. Saya meletakkan inisialisasi WeakReference di onAttach (Konteks konteks), refActivity = new WeakReference <> ((AppCompatActivity) konteks). Dan itu melempar NullPointerException di onCreateView () sesekali.
Kimi Chiu

45

Ini adalah perubahan hebat dari Google ... Modifikasi yang disarankan: ganti onAttach(Activity activity)dengan onAttach(Context context)aplikasi saya yang mogok pada API lama karena onAttach(Context context)tidak akan dipanggil pada fragmen asli.

Saya menggunakan fragmen asli (android.app.Fragment) jadi saya harus melakukan yang berikut untuk membuatnya berfungsi lagi di API yang lebih lama (<23).

Inilah yang saya lakukan:

@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, dapatkah Anda menjelaskan bagaimana melakukannya di atas API 23, mohon bantu saya, terima kasih sebelumnya, E / AndroidRuntime: PENGECUALIAN FATAL: utama, java.lang.ClassCastException: com.ual.SMS_Activity@afd5683, di android. support.v4.app.FragmentManagerImpl.moveToState, di android.support.v4.app.FragmentManagerImpl.execSingleAction. Di sini saya memposting baris yang diperlukan yang akan Anda tahu bug saya.
MohanRaj S

@MohanRajS Ini sama pada API 24 (yang saya gunakan), sesuai dengan kode Anda, masalah Anda tampaknya tidak harus melakukan apa pun dengan ini.
Yoann Hercouet

@YoannHercouet, Terima kasih atas balasan Anda, izinkan saya memeriksa dan memperbarui.
MohanRaj S

1
Anda tidak senang dengan Google tentang hal ini karena kesulitan menargetkan API yang lebih lama. Nah, pertimbangkan berkah bahwa Anda BISA menargetkan API yang lebih tua, sedangkan Apple, misalnya, hanya akan melumpuhkan Anda dan memaksa Anda untuk hanya mendukung yang terbaru.
Stan

39

Jika Anda menggunakan fragmen framework dan versi SDK perangkat lebih rendah dari 23, OnAttach(Context context)tidak akan dipanggil.

Saya menggunakan fragmen dukungan sebagai gantinya, sehingga penghentian diperbaiki dan onAttach(Context context)selalu dipanggil.


11

Saat ini dari onAttachkode Fragmen, tidak jelas apakah Contextaktivitas saat ini: Kode Sumber

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

Jika Anda akan melihat getActivityAnda akan melihat panggilan yang sama

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

Jadi Jika Anda ingin memastikan bahwa Anda memperoleh Kegiatan kemudian gunakan getActivity()(di onAttachdalam Anda Fragment) tapi jangan lupa untuk memeriksa nullkarena jika mHostadalah nullaktivitas Anda akannull


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

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

5

Meskipun tampaknya dalam sebagian besar kasus sudah cukup untuk dimiliki onAttach(Context), ada beberapa telepon (yaitu: Xiaomi Redme Note 2) yang tidak dipanggil, sehingga menyebabkan NullPointerExceptions. Jadi untuk berada di sisi aman saya sarankan untuk meninggalkan metode yang sudah usang juga:

// 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

Unduh pustaka Dukungan terbaru dengan manajer SDK dan sertakan

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

di gradle.app dan atur versi kompilasi ke api 23


1

Jawaban di bawah ini terkait dengan peringatan penghentian ini yang terjadi dalam tutorial Fragmen di situs web pengembang Android dan mungkin tidak terkait dengan posting di atas.

Saya menggunakan kode ini pada pelajaran tutorial dan itu berhasil.

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

    Activity activity = getActivity();

Saya khawatir aktivitas itu mungkin batal seperti yang dinyatakan oleh dokumentasi.

getActivity

FragmentActivity getActivity () Kembalikan FragmentActivity yang saat ini dikaitkan dengan fragmen ini. Dapat mengembalikan nol jika fragmen dikaitkan dengan Konteks sebagai gantinya.

Tetapi onCreate pada main_activity jelas menunjukkan bahwa fragmen dimuat dan setelah metode ini, pemanggilan aktivitas get dari fragmen akan mengembalikan kelas main_activity.

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

Saya harap saya benar dengan ini. Saya seorang pemula yang absolut.


1

Anda mungkin menggunakan android.support.v4.app.Fragment. Untuk ini alih-alih onAttachmetode, cukup gunakan getActivity()untuk mendapatkan FragmentActivityyang terkait dengan fragmen. Lain Anda bisa menggunakan onAttach(Context context)metode.


0

Ini bekerja untuk saya ketika saya memiliki antarmuka 'TopSectionListener', antarmuka aktivitasnya perintah:

  //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());}

}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.