Saya mendapat kesalahan saat menjalankan proyek Android saya untuk RssReader.
Kode:
URL url = new URL(urlToRssFeed);
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader xmlreader = parser.getXMLReader();
RssHandler theRSSHandler = new RssHandler();
xmlreader.setContentHandler(theRSSHandler);
InputSource is = new InputSource(url.openStream());
xmlreader.parse(is);
return theRSSHandler.getFeed();
Dan itu menunjukkan kesalahan di bawah ini:
android.os.NetworkOnMainThreadException
Bagaimana saya bisa memperbaiki masalah ini?
java
android
android-networking
networkonmainthread
bejoy george
sumber
sumber
Jawaban:
Pengecualian ini dilemparkan ketika suatu aplikasi mencoba untuk melakukan operasi jaringan pada utas utamanya. Jalankan kode Anda di
AsyncTask
:Cara menjalankan tugas:
Dalam
MainActivity.java
file Anda dapat menambahkan baris ini dalamoncreate()
metode AndaJangan lupa untuk menambahkan ini ke
AndroidManifest.xml
file:sumber
AsyncTask
, dan menangani perubahan konfigurasi.Anda hampir selalu harus menjalankan operasi jaringan pada utas atau sebagai tugas tidak sinkron.
Tapi itu benar kemungkinan untuk menghapus batasan ini dan Anda menimpa perilaku default, jika Anda bersedia menerima konsekuensinya.
Menambahkan:
Di kelasmu,
dan
TAMBAH izin ini dalam file android manifest.xml:
Konsekuensi:
Aplikasi Anda akan (di area koneksi internet yang berbintik-bintik) menjadi tidak responsif dan terkunci, pengguna merasakan kelambatan dan harus melakukan pemaksaan paksa, dan Anda berisiko manajer aktivitas membunuh aplikasi Anda dan memberi tahu pengguna bahwa aplikasi telah berhenti.
Android memiliki beberapa kiat bagus tentang praktik pemrograman yang baik untuk merancang responsif: http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html
sumber
doInBackground
deklarasi, 2 kurung penutup, dan panggilan keexecute()
). Di sisi lain, bahkan satu pengambilan dari sebuah situs seperti yang Anda sebutkan membawa jeda yang signifikan dalam respons UI. Jangan malas.Saya memecahkan masalah ini menggunakan yang baru
Thread
.sumber
Jawaban yang diterima memiliki beberapa kelemahan. Tidak disarankan menggunakan AsyncTask untuk jaringan kecuali Anda benar - benar tahu apa yang Anda lakukan. Beberapa sisi-bawah meliputi:
executeOnExecutor
metode kelebihan beban dan menyediakan pelaksana alternatif). Kode yang berfungsi dengan baik saat menjalankan serial pada ICS mungkin rusak ketika dieksekusi bersamaan pada Gingerbread, katakan jika Anda memiliki dependensi eksekusi eksekusi yang tidak disengaja.Jika Anda ingin menghindari kebocoran memori jangka pendek, memiliki karakteristik eksekusi yang terdefinisi dengan baik di semua platform, dan memiliki dasar untuk membangun penanganan jaringan yang sangat kuat, Anda mungkin ingin mempertimbangkan:
Service
atauIntentService
sebaliknya, mungkin denganPendingIntent
mengembalikan hasil melalui metode AktivitasonActivityResult
.Pendekatan IntentService
Sisi bawah:
AsyncTask
, meskipun tidak sebanyak yang Anda kiraIntentService
denganService
implementasi yang setara , mungkin seperti ini .Sisi atas:
onActivityResult
metodenyaAsyncTask
dalamActivity
, tetapi jika konteks pengguna-beralih dari aplikasi untuk menerima panggilan telepon, sistem dapat mematikan aplikasi sebelum unggahan selesai. Kecil kemungkinannya untuk mematikan aplikasi dengan aktifService
.IntentService
(seperti yang saya tautkan di atas), Anda dapat mengontrol tingkat konkurensi melaluiExecutor
.Ringkasan implementasi
Anda dapat menerapkan
IntentService
untuk melakukan unduhan pada utas latar belakang tunggal dengan cukup mudah.Langkah 1: Buat sebuah
IntentService
untuk melakukan unduhan. Anda dapat menentukan apa yang harus diunduh melaluiIntent
ekstra, dan meneruskannyaPendingIntent
untuk mengembalikan hasilnya keActivity
:Langkah 2: Daftarkan layanan di manifes:
Langkah 3: Aktifkan layanan dari Aktivitas, dengan meneruskan objek PendingResult yang akan digunakan Layanan untuk mengembalikan hasilnya:
Langkah 4: Tangani hasilnya di onActivityResult:
Proyek Github yang berisi proyek Android-Studio / Gradle yang berfungsi lengkap tersedia di sini .
sumber
IllustrativeRSS
? Bagaimana jika Anda tidak bekerja dengan barang-barang RSS?AsyncTask
. Kesalahan itu dimaksudkan untuk menghentikan pengembang dari tertinggal UI, tidak perlu membujuk mereka untuk mengambil risiko keamanan dengan sekelompok niat / layanan.Anda tidak dapat melakukan I / O jaringan pada utas UI di Honeycomb . Secara teknis, itu adalah dimungkinkan pada versi Android sebelumnya, tetapi itu adalah ide yang sangat buruk karena akan menyebabkan aplikasi Anda berhenti merespons, dan dapat mengakibatkan OS membunuh aplikasi Anda karena berperilaku buruk. Anda harus menjalankan proses latar belakang atau menggunakan AsyncTask untuk melakukan transaksi jaringan Anda di utas latar.
Ada artikel tentang Painless Threading di situs pengembang Android yang merupakan pengantar yang bagus untuk ini, dan itu akan memberi Anda kedalaman jawaban yang jauh lebih baik daripada yang bisa diberikan secara realistis di sini.
sumber
Gunakan Layanan atau AsyncTask
Lihat juga pertanyaan Stack Overflow:
android.os.NetworkOnMainThreadException mengirim email dari Android
sumber
Lakukan tindakan jaringan pada utas lainnya
Dan tambahkan ini ke AndroidManifest.xml
sumber
Anda menonaktifkan mode ketat menggunakan kode berikut:
Ini tidak disarankan : gunakan
AsyncTask
antarmuka.Kode lengkap untuk kedua metode
sumber
Operasi berbasis jaringan tidak dapat dijalankan pada utas utama. Anda perlu menjalankan semua tugas berbasis jaringan pada utas anak atau mengimplementasikan AsyncTask.
Ini adalah bagaimana Anda menjalankan tugas di utas anak:
sumber
Masukkan kode Anda di dalam:
Atau:
sumber
Ini terjadi di Android 3.0 dan di atasnya. Dari Android 3.0 dan di atasnya, mereka telah dibatasi menggunakan operasi jaringan (fungsi yang mengakses Internet) agar tidak berjalan di utas utama / utas UI (apa yang muncul dari metode buat dan pada resume dalam aktivitas).
Ini untuk mendorong penggunaan utas terpisah untuk operasi jaringan. Lihat AsyncTask untuk detail lebih lanjut tentang cara melakukan aktivitas jaringan dengan cara yang benar.
sumber
Menggunakan Android Annotations adalah opsi. Ini akan memungkinkan Anda untuk hanya menjalankan metode apa pun di utas latar:
Perhatikan, bahwa meskipun memberikan manfaat kesederhanaan dan keterbacaan, ia memiliki kelemahan.
sumber
Kesalahan ini karena menjalankan operasi yang berjalan lama di utas utama, Anda dapat dengan mudah memperbaiki masalah dengan menggunakan AsynTask atau Utas . Anda dapat checkout perpustakaan ini AsyncHTTPClient untuk penanganan yang lebih baik.
sumber
Anda seharusnya tidak melakukan tugas yang memakan waktu pada utas utama (utas UI), seperti operasi jaringan, file I / O, atau operasi database SQLite. Jadi untuk jenis operasi ini, Anda harus membuat utas pekerja, tetapi masalahnya adalah Anda tidak dapat secara langsung melakukan operasi terkait UI dari utas pekerja Anda. Untuk itu, Anda harus menggunakan
Handler
dan lulusMessage
.Untuk mempermudah semua hal ini, Android menyediakan berbagai cara, seperti
AsyncTask
,AsyncTaskLoader
,CursorLoader
atauIntentService
. Jadi Anda dapat menggunakan semua ini sesuai dengan kebutuhan Anda.sumber
Jawaban atas spektom bekerja sempurna.
Jika Anda menulis
AsyncTask
inline dan tidak memperluas sebagai kelas, dan di atas semua ini, jika ada kebutuhan untuk mendapatkan respons dariAsyncTask
, Anda dapat menggunakanget()
metode seperti di bawah ini.(Dari contohnya.)
sumber
get()
adalah ide yang buruk ... itu membuat AsyncTask "disinkronkan" lagiIni hanya dibuang untuk aplikasi yang menargetkan Honeycomb SDK atau lebih tinggi. Aplikasi yang menargetkan versi SDK sebelumnya diizinkan untuk melakukan jaringan di utas loop acara utama.
Kesalahannya adalah peringatan SDK!
sumber
Bagi saya ini:
Perangkat tempat saya menguji aplikasi saya adalah 4.1.2 yang merupakan SDK Versi 16!
Pastikan versi targetnya sama dengan Pustaka Target Android Anda. Jika Anda tidak yakin apa perpustakaan target Anda, klik kanan Proyek Anda -> Build Path -> Android , dan itu harus menjadi salah satu yang dicentang.
Juga, seperti yang disebutkan orang lain, sertakan izin yang benar untuk mengakses Internet:
sumber
NetworkOnMainThreadException
adalah Guardian yang memberi tahu Anda: jangan menembak di kaki Anda sendiri ... solusinya adalah: mari kita kembali ke masa lalu ketika tidak ada Guardian - sekarang saya bisa menembak pada saya kaki dengan bebasGunakan ini di Aktivitas Anda
sumber
Hanya untuk mengeja sesuatu secara eksplisit:
Utas utama pada dasarnya adalah utas UI.
Jadi mengatakan bahwa Anda tidak dapat melakukan operasi jaringan di utas utama berarti Anda tidak dapat melakukan operasi jaringan di utas UI, yang berarti Anda tidak dapat melakukan operasi jaringan di
*runOnUiThread(new Runnable() { ... }*
blok di dalam utas lainnya.(Saya baru saja mengalami saat-saat menggaruk-garuk kepala yang panjang untuk mencari tahu mengapa saya mendapatkan kesalahan di tempat lain selain utas utama saya. Inilah sebabnya; utas ini membantu; dan semoga komentar ini akan membantu orang lain.)
sumber
Pengecualian ini terjadi karena tugas berat yang dilakukan pada utas utama jika tugas tersebut membutuhkan terlalu banyak waktu .
Untuk menghindari ini, kita bisa menanganinya menggunakan utas atau pelaksana
sumber
Sudah ada banyak jawaban bagus untuk pertanyaan ini, tetapi banyak perpustakaan hebat telah keluar sejak jawaban-jawaban itu diposting. Ini dimaksudkan sebagai semacam panduan pemula.
Saya akan membahas beberapa kasus penggunaan untuk melakukan operasi jaringan dan satu atau dua solusi untuk masing-masingnya.
REST melalui HTTP
Biasanya Json, bisa berupa XML atau yang lainnya
Akses API Penuh
Katakanlah Anda sedang menulis aplikasi yang memungkinkan pengguna melacak harga saham, suku bunga, dan nilai tukar saat ini. Anda menemukan API Json yang terlihat seperti ini:
Retrofit dari Square
Ini adalah pilihan yang sangat baik untuk API dengan banyak titik akhir dan memungkinkan Anda untuk mendeklarasikan titik akhir REST daripada harus kode mereka secara individual seperti dengan perpustakaan lain seperti ion atau Volley. (situs web: http://square.github.io/retrofit/ )
Bagaimana Anda menggunakannya dengan API keuangan?
build.gradle
Tambahkan baris ini ke buid.gradle tingkat Modul Anda:
FinancesApi.java
Pembangun Keuangan
Cuplikan Keuangan
Jika API Anda memerlukan Kunci API atau tajuk lainnya seperti token pengguna, dll. Untuk dikirim, Retrofit membuatnya mudah (lihat jawaban yang luar biasa ini untuk detailnya: https://stackoverflow.com/a/42899766/1024412 ).
Sekali lagi akses API REST
Katakanlah Anda sedang membangun aplikasi "mood mood" yang mencari lokasi pengguna GPS dan memeriksa suhu saat ini di area itu dan memberi tahu mereka mood. Jenis aplikasi ini tidak perlu mendeklarasikan titik akhir API; itu hanya perlu dapat mengakses satu titik akhir API.
Ion
Ini adalah perpustakaan yang bagus untuk jenis akses ini.
Silakan baca jawaban hebat msysmilu ( https://stackoverflow.com/a/28559884/1024412 )
Memuat gambar melalui HTTP
Tembakan
Volley juga dapat digunakan untuk API REST, tetapi karena pengaturan yang lebih rumit diperlukan saya lebih suka menggunakan Retrofit dari Square seperti di atas ( http://square.github.io/retrofit/ )
Katakanlah Anda sedang membangun aplikasi jejaring sosial dan ingin memuat foto profil teman.
build.gradle
Tambahkan baris ini ke buid.gradle tingkat Modul Anda:
ImageFetch.java
Volley membutuhkan lebih banyak pengaturan daripada Retrofit. Anda perlu membuat kelas seperti ini untuk menyiapkan RequestQueue, ImageLoader, dan ImageCache, tapi itu tidak terlalu buruk:
user_view_dialog.xml
Tambahkan berikut ini ke file xml tata letak Anda untuk menambahkan gambar:
UserViewDialog.java
Tambahkan kode berikut ke metode onCreate (Fragmen, Aktivitas) atau konstruktor (Dialog):
Picasso
Perpustakaan lain yang sangat baik dari Square. Silakan lihat situs untuk beberapa contoh bagus: http://square.github.io/picasso/
sumber
Dengan kata-kata sederhana,
JANGAN LAKUKAN JARINGAN DI THREAD UI
Misalnya, jika Anda melakukan permintaan HTTP, itu adalah tindakan jaringan.
Larutan:
Cara:
Letakkan semua karya Anda di dalamnya
run()
metode utas barudoInBackground()
metode kelas AsyncTask.Tapi:
Ketika Anda mendapatkan sesuatu dari respons Jaringan dan ingin memperlihatkannya pada tampilan Anda (seperti menampilkan pesan respons di TextView), Anda perlu kembali ke utas UI .
Jika Anda tidak melakukannya, Anda akan mendapatkannya
ViewRootImpl$CalledFromWrongThreadException
.Bagaimana caranya?
onPostExecute()
metoderunOnUiThread()
metode dan perbarui tampilan di dalamrun()
metode.sumber
Anda dapat memindahkan bagian dari kode Anda ke utas lain untuk melepaskan
main thread
dan menghindari mendapatkan ANR , NetworkOnMainThreadException , IllegalStateException (mis. Tidak dapat mengakses database pada utas utama karena berpotensi mengunci UI untuk jangka waktu yang lama).Ada beberapa pendekatan yang harus Anda pilih tergantung situasi
Java Thread atau Android HandlerThread
AsyncTask
Implementasi pool thread ThreadPoolExecutor , DijadwalkanThreadPoolExecutor ...
FutureTask
AsyncTaskLoaders
IntentService
Penjadwal Pekerjaan
RxJava
Coroutines (Kotlin)
Baca lebih lanjut di sini , di sini , di sini , di sini
sumber
Meskipun di atas ada kumpulan solusi besar, tidak ada yang disebutkan
com.koushikdutta.ion
: https://github.com/koush/ionIni juga tidak sinkron dan sangat mudah digunakan:
sumber
Solusi baru
Thread
dan AsyncTask telah dijelaskan.AsyncTask
idealnya digunakan untuk operasi pendek. NormalThread
tidak disukai untuk Android.Lihatlah solusi alternatif menggunakan HandlerThread dan Handler
HandlerThread
Handler:
Larutan:
Membuat
HandlerThread
Hubungi
start()
diHandlerThread
Buat
Handler
dengan mendapatkanLooper
dariHanlerThread
Cantumkan kode terkait operasi Jaringan Anda di
Runnable
objekKirim
Runnable
tugas keHandler
Cuplikan kode contoh, yang alamatnya
NetworkOnMainThreadException
Kelebihan menggunakan pendekatan ini:
Thread/AsyncTask
untuk setiap operasi jaringan itu mahal. IniThread/AsyncTask
akan dimusnahkan dan diciptakan kembali untuk operasi Jaringan berikutnya. Tapi denganHandler
danHandlerThread
pendekatan, Anda bisa mengirimkan banyak operasi jaringan (sebagai tugas Runnable) untuk tunggalHandlerThread
dengan menggunakanHandler
.sumber
RxAndroid
adalah alternatif lain yang lebih baik untuk masalah ini dan ini menyelamatkan kita dari kerepotan membuat utas dan kemudian memposting hasil pada utas Android UI. Kami hanya perlu menentukan utas yang tugasnya harus dijalankan dan semuanya ditangani secara internal.Dengan menentukan
(Schedulers.io())
, RxAndroid akan berjalangetFavoriteMusicShows()
pada utas yang berbeda.Dengan menggunakan
AndroidSchedulers.mainThread()
kami ingin mengamati ini Teramati pada utas UI, yaitu kami inginonNext()
panggilan balik kami dipanggil pada utas UIsumber
Utas utama adalah utas UI, dan Anda tidak dapat melakukan operasi pada utas utama yang dapat memblokir interaksi pengguna. Anda dapat memecahkan ini dengan dua cara:
Paksa untuk melakukan tugas di utas utama seperti ini
Atau buat handler sederhana dan perbarui utas utama jika Anda mau.
Dan untuk menghentikan penggunaan utas:
Untuk informasi lebih lanjut lihat ini: threading menyakitkan
sumber
Ini bekerja. Baru saja membuat jawaban Dr.Luiji sedikit lebih sederhana.
sumber
Di Android, operasi jaringan tidak dapat dijalankan di utas utama. Anda dapat menggunakan Utas, AsyncTask (tugas jangka pendek), Layanan (tugas jangka panjang) untuk melakukan operasi jaringan.
sumber
Mengakses sumber daya jaringan dari utas utama (UI) menyebabkan pengecualian ini. Gunakan utas terpisah atau AsyncTask untuk mengakses sumber daya jaringan untuk menghindari masalah ini.
sumber