Android Asenkron Resim Gösterimi (URL - Web'den)

Şu sıralar yeni bir Android projesi ile uğraşmaktayım. Bu seferki projem diğerlerinden farklı olarak bana ait markete koymak için yaptığım bir proje değil. Projenin detaylarına girmeden kısaca başımdan geçen bir olayı sizinle paylaşmak istedim.

Projenin bir menüsünde sunucudan alınan veriler üzerinden yine sunucuda bulunan resimlerin gösterilmesi gerekiyordu. Basitçe “Android ile url (web) kullanarak nasıl resim gösteririm?” sorusunun cevabını araştırmam gerekiyordu.

Dilerseniz ufak bir kod parçasıyla bunu nasıl yaptığımı size özetleyebilirim.

public static Drawable LoadImageFromWebOperations(String url) { try { InputStream is = (InputStream) new URL(url).getContent(); return Drawable.createFromStream(is, "name"); } catch (Exception e) { Log.e("LoadImage", "exception", e); return img.getResources().getDrawable(R.drawable.noimage); } }

Yukarıdaki fonksiyonu statik olarak tanımlarsanız sadece parametre göndererek url'den resminizi elde etmiş olacaksınız.

Bir fonksiyon ile URL’den resim dönüşümü yaptıktan sonra işlerin kolaylaştığını düşünerek uygulamayı çalıştırdım. Uygulama içerisinden resim gösterme kısmına geldiğimde ise hata aldım.

"android.os.NetworkOnMainThreadException"

Hata için önce yazdığım koddan şüphelenip değişik kodlamalar denedikten sonra cevap bulamayınca Google araştırmalarına başladım.  Hatanın tanımı geniş kapsamlı olsa da çözüm sürecinde çoğunlukla “AsyncTask” sınıfıyla karşılaştım. Uygulamamda ilgili ekran için bilgiler bir Thread aracılığıyla Web servis üzerinden alınıyor ve gelen bilgiler ile resimlerin aynı zamanda web’den çekilmesi gerekiyordu. İki network (internet-ağ) işleminin aynı Thread üzerinde aynı anda başlaması sorunun kendisi oluyormuş. Dolayısıyla çözüm için değişiklik şart oldu ve “AsyncTask” sınıfını kullanma gerekliliği ortaya çıktı.

public class LoadImage extends AsyncTask<ImageView, Void, Drawable> { ImageView img; public Drawable LoadImageFromWebOperations(String url) {
try { InputStream is = (InputStream) new URL(url).getContent(); return Drawable.createFromStream(is, "isim"); } catch (Exception e) { Log.e("LoadImageFromWeb", "Hata", e); return img.getResources().getDrawable(R.drawable.noimage); } } @Override protected Drawable doInBackground(ImageView... params) { img = params[0]; return LoadImageFromWebOperations(img.getTag().toString()); } @Override protected void onPostExecute(Drawable result) { img.setImageDrawable(result); }

Async sınıfını kullanarak Thread ile web servis üzerinden aldığım veriyi asenkron iletişime dahil ederek resimlerin gelmesini sağladım. Bu sayede aynı Thread üzerinde web servis ve resim download işleminden vazgeçtim. Yalnız net olmasa da bu hatanın Android 4.0.3 (Ice Cream Sandwich) versiyonundan düşük versiyonlar için kaynaklandığına bir yerde rastladım. Uygulamayı genele yaymak için düşük versiyonlar şart olduğundan çözümü asenkron hale dönüştürmek zorunda kaldım.

Aslında çok basit bir şekilde Thread işleminden vazgeçerek en üstte belirtiğim statik fonksiyonu kullanabilirdim. Fakat uygulama geliştirirken bazen basitlikten çıkmak gerekiyor. Uygulama ekranında Thread kullanmadan yaptığımızda verinin gelme zamanına bağlı olarak ekran donup kalıyor ve kullanıcıya bu durumu izah edemiyorsunuz. Verinin gelmesi ve ekranın düzenlenmesi sırasında Progress Dialog (Yükleniyor ekranı) çıkartarak kullanıcıyı veri hakkında haberdar edebiliyorsunuz. Son olarak thread ile progress dialog nasıl çıkarılır? Yükleniyor (Loading) ekranı ile kullanıcı nasıl haberdar edilir? diye düşünüyorsanız aşağıdaki fonksiyon yardımcınız olur umarım.

Handler mHandler = new Handler(); private void threadprogressdialogyukleme() { // Bu işlemin activity icinde oldugu dusunuluyor // this = Activity final ProgressDialog dialog = ProgressDialog.show(this, "", "Yükleniyor..."); new Thread(new Runnable() { public void run() { get();//Datanın cekildigi yer mHandler.post(new Runnable() { public void run() { // Data çekildikten sonra bu kısımda // gerekli arayüz düzenlemesi yapılabilir. dialog.dismiss(); //Yukleniyor ekranı kapatılır. } }); } }).start(); }

Yorum Gönderme