Bayangkan saya berada di Layanan yang sudah memiliki utas latar belakang. Bisakah saya melakukan permintaan menggunakan voli di utas yang sama, sehingga panggilan balik terjadi secara serempak?
Ada 2 alasan untuk ini: - Pertama, saya tidak perlu utas lainnya dan akan sia-sia untuk membuatnya. - Kedua, jika saya menggunakan ServiceIntent, eksekusi utas akan selesai sebelum panggilan balik, dan karenanya saya tidak akan mendapat respons dari Volley. Saya tahu saya dapat membuat Layanan saya sendiri yang memiliki beberapa utas dengan runloop yang dapat saya kendalikan, tetapi akan sangat diinginkan memiliki fungsi ini dalam voli.
Terima kasih!
java
android
android-volley
LocoMike
sumber
sumber
Jawaban:
Sepertinya itu mungkin dengan
RequestFuture
kelas Volley . Misalnya, untuk membuat permintaan GET HTTP JSON sinkron, Anda dapat melakukan hal berikut:sumber
JsonObjectRequest(String url, JSONObject jsonRequest, Listener<JSONObject> listener, ErrorListener errorlistener)
konstruktor.RequestFuture<JSONObject>
mengimplementasikan keduaListener<JSONObject>
danErrorListener
antarmuka, sehingga dapat digunakan sebagai dua parameter terakhir.future.get()
maka aplikasi akan berhenti atau mengalami batas waktu pasti jika diatur demikian.Catatan @Matthews jawaban benar TETAPI jika Anda berada di utas lainnya dan Anda melakukan panggilan voli ketika Anda tidak memiliki internet, panggilan balik kesalahan Anda akan dipanggil pada utas utama, tetapi utas yang Anda ikuti akan diblokir SELAMANYA. (Oleh karena itu jika utas itu adalah IntentService, Anda tidak akan pernah bisa mengirim pesan lain padanya dan layanan Anda pada dasarnya mati).
Gunakan versi
get()
yang memiliki batas waktufuture.get(30, TimeUnit.SECONDS)
dan tangkap kesalahan untuk keluar dari utas Anda.Untuk mencocokkan jawaban @Mathews:
Di bawah ini saya membungkusnya dengan metode & menggunakan permintaan yang berbeda:
sumber
IntentService
adalah pelaksana kumpulan thread dari satu utas, oleh karena itu IntentService akan diblokir selamanya saat ia duduk dalam satu lingkaranMungkin disarankan untuk menggunakan Futures, tetapi jika karena alasan apa pun Anda tidak mau, alih-alih memasak blokir tersinkronisasi Anda sendiri, Anda harus menggunakan a
java.util.concurrent.CountDownLatch
. Jadi itu akan bekerja seperti ini ..Karena orang-orang tampaknya benar-benar mencoba melakukan ini dan mengalami beberapa masalah, saya memutuskan untuk menyediakan contoh nyata "kehidupan nyata" yang digunakan ini. Ini dia https://github.com/timolehto/SynchronousVolleySample
Sekarang meskipun solusinya bekerja, ia memiliki beberapa keterbatasan. Yang terpenting, Anda tidak dapat menyebutnya di utas UI utama. Volley memang mengeksekusi permintaan di latar belakang, tetapi secara default Volley menggunakan utama
Looper
aplikasi untuk mengirim respons. Ini menyebabkan jalan buntu karena utas UI utama sedang menunggu respons, tetapiLooper
menunggu untukonCreate
selesai sebelum memproses pengiriman. Jika Anda benar-benar ingin melakukan ini, Anda bisa, alih-alih metode pembantu statis, instantiate Anda sendiri yangRequestQueue
melewatinya, Anda sendiri yangExecutorDelivery
terkait denganHandler
penggunaanLooper
yang diikat ke utas berbeda dari utas UI utama.sumber
Sebagai pengamatan komplementer untuk jawaban @Blundells dan @Mathews, saya tidak yakin ada panggilan yang dikirim ke apa pun kecuali utas utama oleh Volley.
Sumber
Melihat
RequestQueue
implementasi tampaknyaRequestQueue
menggunakanNetworkDispatcher
untuk mengeksekusi permintaan danResponseDelivery
untuk memberikan hasil (yangResponseDelivery
disuntikkan ke dalamNetworkDispatcher
). PadaResponseDelivery
gilirannya dibuat denganHandler
menelurkan dari utas utama (suatu tempat sekitar baris 112 dalamRequestQueue
implementasi).Di suatu tempat sekitar baris 135 di
NetworkDispatcher
implementasi sepertinya juga hasil yang berhasil disampaikan melalui samaResponseDelivery
seperti kesalahan. Lagi; aResponseDelivery
berdasarkanHandler
menelurkan dari utas utama.Alasan
Untuk kasus penggunaan di mana permintaan harus dibuat dari
IntentService
adil untuk menganggap bahwa utas layanan harus diblokir sampai kami mendapat respons dari Volley (untuk menjamin ruang lingkup runtime hidup untuk menangani hasilnya).Solusi yang disarankan
Salah satu pendekatan akan menggantikan cara default a
RequestQueue
dibuat , di mana konstruktor alternatif digunakan sebagai gantinya, menyuntikkanResponseDelivery
yang memunculkan dari utas saat ini daripada utas utama. Saya belum menyelidiki implikasi dari ini.sumber
finish()
metode diRequest
kelas danRequestQueue
kelas adalah paket pribadi, selain dari menggunakan hack refleksi saya tidak yakin ada jalan keluarnya. Apa yang saya akhirnya lakukan untuk mencegah sesuatu berjalan pada utas utama (UI) adalah membuat utas alternatif Looper (menggunakanLooper.prepareLooper(); Looper.loop()
) dan meneruskan sebuahExecutorDelivery
instance keRequestQueue
konstruktor dengan handler untuk looper itu. Anda memiliki overhead dari looper lain tetapi tetap berada di utas utamaSaya menggunakan kunci untuk mencapai efek itu sekarang saya bertanya-tanya apakah itu benar cara saya ada yang mau berkomentar?
sumber
catch (InterruptedException e)
dalam loop sementara. Kalau tidak, utas akan gagal menunggu jika terputus karena alasan tertentuSaya ingin menambahkan sesuatu ke jawaban Matius yang diterima. Sementara
RequestFuture
sepertinya membuat panggilan sinkron dari utas yang Anda buat, itu tidak. Sebaliknya, panggilan dieksekusi di utas latar belakang.Dari apa yang saya pahami setelah melalui perpustakaan, permintaan dalam
RequestQueue
dikirim denganstart()
metode:Sekarang keduanya
CacheDispatcher
danNetworkDispatcher
kelas memperpanjang utas. Begitu efektifnya sebuah utas pekerja baru ditelurkan untuk mengeluarkan antrian permintaan dan respons dikembalikan ke keberhasilan dan kesalahan pendengar yang diterapkan secara internal olehRequestFuture
.Meskipun tujuan kedua Anda tercapai tetapi tujuan pertama Anda bukan karena utas baru selalu muncul, tidak peduli dari utas mana Anda menjalankan
RequestFuture
.Singkatnya, permintaan sinkron yang sebenarnya tidak dimungkinkan dengan pustaka Volley default. Koreksi saya jika saya salah.
sumber
Anda dapat melakukan permintaan sinkronisasi dengan volley tetapi Anda harus memanggil metode di utas yang berbeda atau aplikasi Anda yang berjalan akan diblokir, harus seperti ini:
setelah itu Anda dapat memanggil metode di utas:
sumber