Saya membuat permintaan dapatkan HTTP ke situs web untuk aplikasi android yang saya buat.
Saya menggunakan DefaultHttpClient dan menggunakan HttpGet untuk mengeluarkan permintaan. Saya mendapatkan respons entitas dan dari sini mendapatkan objek InputStream untuk mendapatkan html halaman.
Saya kemudian melakukan balas dengan melakukan sebagai berikut:
BufferedReader r = new BufferedReader(new InputStreamReader(inputStream));
String x = "";
x = r.readLine();
String total = "";
while(x!= null){
total += x;
x = r.readLine();
}
Namun ini sangat lambat.
Apakah ini tidak efisien? Saya tidak memuat halaman web besar - www.cokezone.co.uk sehingga ukuran file tidak besar. Apakah ada cara yang lebih baik untuk melakukan ini?
Terima kasih
Andy
Jawaban:
Masalah dalam kode Anda adalah membuat banyak
String
objek berat , menyalin kontennya dan melakukan operasi padanya. Sebagai gantinya, Anda harus menggunakanStringBuilder
untuk menghindari membuatString
objek baru di setiap append dan untuk menghindari menyalin array char. Implementasi untuk kasus Anda akan menjadi seperti ini:Anda sekarang dapat menggunakan
total
tanpa mengubahnya menjadiString
, tetapi jika Anda membutuhkan hasilnya sebagaiString
, cukup tambahkan:Hasil string = total.toString ();
Saya akan mencoba menjelaskannya dengan lebih baik ...
a += b
(ataua = a + b
), di manaa
danb
sekarang, menyalin konten keduanyaa
danb
ke objek baru (perhatikan bahwa Anda juga menyalina
, yang berisi akumulasiString
), dan Anda melakukan salinan itu pada setiap iterasi.a.append(b)
, di manaa
aStringBuilder
, langsung menambahkanb
kontena
, sehingga Anda tidak menyalin string yang terakumulasi di setiap iterasi.sumber
StringBuilder total = new StringBuilder(inputStream.available());
readline
loop adalah konyol. Pola itu seharusnya mati dengan kacang hijau di tahun 70-an.Sudahkah Anda mencoba metode bawaan untuk mengonversi aliran ke string? Itu bagian dari perpustakaan Apache Commons (org.apache.commons.io.IOUtils).
Maka kode Anda adalah baris ini:
Dokumentasi untuk itu dapat ditemukan di sini: http://commons.apache.org/io/api-1.4/org/apache/commons/io/IOUtils.html#toString%28java.io.InputStream%29
Perpustakaan IO Apache Commons dapat diunduh dari sini: http://commons.apache.org/io/download_io.cgi
sumber
Kemungkinan lain dengan Jambu Biji:
ketergantungan:
compile 'com.google.guava:guava:11.0.2'
sumber
Saya percaya ini cukup efisien ... Untuk mendapatkan sebuah String dari InputStream, saya akan memanggil metode berikut:
Saya selalu menggunakan UTF-8. Anda tentu saja dapat menetapkan rangkaian karakter sebagai argumen, selain InputStream.
sumber
Bagaimana dengan ini. Tampaknya memberikan kinerja yang lebih baik.
Sunting: Sebenarnya ini mencakup steelbytes dan Maurice Perry
sumber
Mungkin agak lebih cepat daripada jawaban Jaime Soriano, dan tanpa masalah pengkodean multi-byte dari jawaban Adrian, saya sarankan:
sumber
Mungkin lebih baik daripada membaca 'satu baris pada satu waktu' dan bergabung dengan string, coba 'baca semua yang tersedia' untuk menghindari pemindaian untuk akhir baris, dan juga untuk menghindari string bergabung.
yaitu,
InputStream.available()
danInputStream.read(byte[] b), int offset, int length)
sumber
Membaca satu baris teks pada satu waktu, dan menambahkan baris kata ke string secara individual memakan waktu baik dalam mengekstraksi setiap baris dan overhead dari begitu banyak doa metode.
Saya bisa mendapatkan kinerja yang lebih baik dengan mengalokasikan byte array berukuran layak untuk menampung data stream, dan yang secara iteratif diganti dengan array yang lebih besar bila diperlukan, dan mencoba membaca sebanyak yang bisa disimpan oleh array.
Untuk beberapa alasan, Android berulang kali gagal mengunduh seluruh file ketika kode menggunakan InputStream yang dikembalikan oleh HTTPUrlConnection, jadi saya harus menggunakan BufferedReader dan mekanisme timeout linting tangan untuk memastikan saya mendapatkan seluruh file atau membatalkan transfer.
EDIT: Ternyata jika Anda tidak perlu menyandikan ulang konten (yaitu, Anda menginginkan konten SEBAGAIMANA ADANYA ), Anda tidak boleh menggunakan subkelas Pustaka apa pun. Cukup gunakan subkelas Stream yang sesuai.
Ganti awal metode sebelumnya dengan garis yang sesuai di bawah ini untuk mempercepatnya 2 hingga 3 kali lipat .
sumber
Jika file panjang, Anda dapat mengoptimalkan kode dengan menambahkan ke StringBuilder alih-alih menggunakan penggabungan String untuk setiap baris.
sumber
sumber
Untuk mengonversi InputStream ke String, kami menggunakan metode BufferedReader.readLine () . Kami beralih sampai BufferedReader mengembalikan nol yang berarti tidak ada lagi data untuk dibaca. Setiap baris akan ditambahkan ke StringBuilder dan dikembalikan sebagai String.
Dan akhirnya dari kelas mana pun di mana Anda ingin mengkonversi panggilan fungsi
lengkap
sumber
Saya terbiasa membaca data lengkap:
sumber