Bagaimana cara mengakses dialog dari proses latar belakang?

Saya memiliki ListView dengan adaptor khusus dan itu menunjukkan daftar wifi di sekitar saya. Ketika satu item diklik, saya menampilkan dialog dengan detail. Dialognya adalah kelas khusus yang diturunkan dari DialogFragment dan ditampilkan menggunakan kode ini setelah pemindaian Wifi selesai:

private class WifiScanReceiver extends BroadcastReceiver {
        public void onReceive(Context c, Intent intent) {
            List<ScanResult> wifiScanList = wifi.getScanResults();
            Log.i("WifiAnal", "rec");

            lv.setAdapter(new WifiListAdapter(getApplicationContext(), R.layout.itemlistrow, wifiScanList));
            lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    ScanResult listItem = (ScanResult)lv.getItemAtPosition(position);
                    WifiDetailsDialogFragment d = new WifiDetailsDialogFragment();

                    // Supply num input as an argument.
                    Bundle args = new Bundle();
                    args.putString("ssid", listItem.SSID);

                    d.setArguments(args);

                    d.show(getSupportFragmentManager(), "fir");

                    // TODO: PUT ASYNC CALL HERE AND PROCESS FETCHED DATA.
                    // TODO: SHOW ASYNC RESULT ON OPEN DIALOG

                }

            });

            mSwipeRefreshLayout.setRefreshing(false);
        }
    }

Kelas WifiDetailsDialogFragment saya menangani pengembangan tata letak xmlnya dan menampilkannya dengan benar di atas aplikasi dengan tombol Ok.

Sekarang bayangkan saya menampilkan dialog dan sekarang saya ingin menjalankan tugas latar belakang (misalnya mengambil beberapa detail lebih lanjut dari DB di server eksternal) dan setelah saya selesai, jika dialog masih terbuka, masukkan hasilnya ke dalam tata letaknya (kemungkinan memanipulasi nilai beberapa TextViews yang sudah ada dan di-inflate). Jika sudah ditutup pada saat itu, jangan lakukan apa pun.

Bagaimana cara mengakses widget tata letak saya dari proses yang berjalan di latar belakang yang diprakarsai oleh onItemClick? Saya mencoba d.getView() tetapi ini mengembalikan null. Apakah cara yang benar melalui FragmentManager? Saya tidak ingin membuat dialog baru, melainkan mengedit anggota yang sudah ada.

Terima kasih!


person michnovka    schedule 21.10.2015    source sumber
comment
Anda tidak dapat mengakses tampilan utas UI dari utas latar belakang Anda, setelah Anda mendapatkan nilai yang diambil dari DB atau dari panggilan server pada metode runOnUIThread, lalu lakukan apa pun yang ingin Anda lakukan dengan fragmen dialog Anda.   -  person dex    schedule 21.10.2015
comment
bagaimana saya bisa mendapatkan referensi ke TextView di dalam dialog dari dalam runOnUIThread? Tata letaknya diperluas dari dalam onItemClick   -  person michnovka    schedule 21.10.2015
comment
Anda harus meneruskannya ke utas latar belakang melalui referensi yang lemah, saya kira.   -  person dex    schedule 21.10.2015


Jawaban (2)


Nah, jika Anda hanya ingin mengakses fragmen Anda, Anda bisa menggunakannya

getSupportFragmentManager().findFragmentByTag("fir")

Tag ini harus ditentukan pada saat transaksi fragmen Anda (dalam kasus Anda show() karena ini adalah DialogFragment.

Tapi saya harus menyarankan bahwa kode yang Anda tetapkan di atas terlihat sedikit aneh. Bagaimana Anda mengharapkan hasil panggilan async Anda langsung terlihat? Jika Anda melanjutkan dengan kode seperti ini Anda akan mendapatkan android.os.NetworkOnMainThreadException

Untuk menghindarinya, Anda harus membuat AsyncTask dan memanipulasi UI Anda pada metode onPostExecute, tempat Anda akan kembali ke loop utama.

person luis.mazoni    schedule 21.10.2015
comment
Saya melakukan panggilan menggunakan AsyncTask, di sinilah saya menjalankannya, ia akan memiliki metodenya sendiri termasuk metode onPostExecute dan di situlah saya perlu menangani TextView. Jadi apakah solusi ini akan berhasil dalam situasi seperti ini? - person michnovka; 21.10.2015
comment
GetFragment juga memerlukan Bundle sebagai parameter pertama. Apa yang harus saya taruh di sana? Mengapa diperlukan, apakah dibuat dari awal? - person michnovka; 21.10.2015
comment
maaf, gunakan: findFragmentByTag - person luis.mazoni; 21.10.2015
comment
Saya menambahkan kode ini ((WifiDetailsDialogFragment)getSupportFragmentManager().findFragmentByTag("fir")).updateUI(); tepat setelah d.show(getSupportFragmentManager(), "fir"); dan saya mendapatkan nullPointerException, artinya saya tidak mendapatkan fragmen yang benar dengan cara ini, saya malah mendapatkan null... tahu kenapa? P.S. updateUI() adalah fungsi yang ditentukan dalam fragmen khusus saya yang menangani perubahan yang diperlukan - person michnovka; 21.10.2015

Saya menyarankan Anda menggunakan Otto untuk mengirim peristiwa dari thread latar belakang Anda ke logika UI. Peristiwa ini mungkin berisi informasi apa pun yang Anda perlukan. Langkah-langkah yang harus Anda ikuti adalah:

  • Suntikkan bus Anda di thread latar belakang dan fragmen dialog (dapat bervariasi sesuai dengan solusi manajer ketergantungan Anda)
  • register() pecahanmu ke bus
  • Buat metode yang menerima acara dan beri anotasi dengan @Subscribe
  • post() acara dari thread latar belakang (untuk melakukannya Anda harus pergi ke looper utama tetapi itu dapat dengan mudah dilakukan dengan memodifikasi otto bus seperti kode di bawah)

    public class MainThreadBus extends Bus {
     private final Handler handler = new Handler(Looper.getMainLooper());
    
     @Override public void post(final Object event) {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            super.post(event);
        } else {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    MainThreadBus.super.post(event);
                }
            });
        }
    }
    

Kode ini disarankan dalam jawaban ini: Bagaimana cara mengirim acara dari Layanan ke Aktivitas dengan bus acara Otto?

Menulis solusi Anda dengan cara ini sebenarnya akan lebih aman karena Anda dapat unregister() fragmen Anda pada metode onPause, oleh karena itu Anda tidak perlu memeriksa apakah fragmen tersebut masih melekat pada suatu aktivitas saat memanipulasi UI-nya.

person luis.mazoni    schedule 21.10.2015
comment
Terima kasih, tetapi sepertinya agak berlebihan untuk hal sederhana seperti itu. Saya mencari sth tanpa komponen pihak ketiga - person michnovka; 21.10.2015