Saturday, June 1, 2013

Android Out Of Memory Setelah Memanggil Bitmap

Akhirnya kami bisa juga bikin tampilannya dengan klik tombol dan berpindah layar. Layouting juga bisa dipakai, dan yang lebih maknyusnya, layoutnya responsif berdasarkan besar layar. Pertanyaan intermezzo, kenapa nggak pake framework/engine game? Aih, sudah terlanjur terkerjakan. Maybe later... heheh.. Tapi karena nggak pake engine game yang sudah ada, pastinya harus main-main di cara ngerender gambarnya. Ini merepotkan.
Tadaaaa~~ Layoutnya. Warnanya merah nyeremin kata @ndaindana. Hehe, ini cuman buat nyobain ngetest "jalan" aja sebenarnya, kalo warnanya putih pas ngetest suka disangka nge-hang

Masalah

Setelah mengerti cara membuat view dengan framework-framework-an yang kami bikin, kemudian kami membagi tugas untuk membuat tampilan (view) masing-masing. Hasilnya jadi dan sesuai yang diharapkan. Tapi ternyata ketika saya menekan tombol game dan kembali, berulang-ulang, dapatnya Out Of Memory!

Ah~ Menyebalkan deh kalau hubungannya sama memory. Berarti harus optimasi.

Setelah membaca beberapa artikel dan diskusi stackoverflow, ternyata bitmap dalam Android memang ribet dan bermasalah.

Beberapa link artikel setelah beberapa waktu di-Googling:
http://stackoverflow.com/questions/11201502/clean-memory-in-android/11201652#11201652
http://ttlnews.blogspot.com/2010/01/attacking-memory-problems-on-android.html
http://blog.pseudoblue.com/2010/08/15/android-bitmaps-and-memory-leaks/

Katanya Bitmap dalam Android berada di bagian dari aplikasi yang tidak disentuh oleh Garbage Collector (GC), akhirnya memori bertambah terus karena saya panggil di onCreate.

Solusi

Untuk itu solusinya pada proyek ini adalah dengan melakukan bmp.recycle() DI SETIAP bitmap yang digunakan agar bisa "disentuh" oleh GC. Karena repot jika harus melakukan blablabla.recycle() di setiap Entity yang dibuat, maka saya sudah membuatkan method khusus di dalam GameView, jadi tinggal pakai. Sekalian aja supaya kegiatan yang selama ini dilakukan berulang terhadap Entity digabungkan. Jadi bersiaplah dengan.... jreng jeng jeng... EntityCollection!

Cara Pakai Method Baru

1. addEntity
Method ini menambahkan entity apa saja yang ada dalam view. Jadi semua entity yang dipakai HARUS DIMASUKKAN ke dalam addEntity ini.

ini contoh yang digunakan dalam view Petualangan
 
  einfo = new EInfobar(getResources());
  ebardistance = new EBarDistance(getResources());
  edistance = new EDistance(getResources());
  ehealthpoint = new EHealthPoint(getResources());
  ebarhealth = new EBarHealth(getResources());
  egameview = new EGameView(getResources());
  estars = new EStars(getResources());
  esteps = new ESteps(getResources());
  eshop = new EShop(getResources());
  epotion = new EPotion(getResources());
  elevel = new ELevel(getResources());
  ecalore = new ECalore(getResources());
  
  addEntity(einfo, ebardistance, edistance,
     ehealthpoint, ebarhealth, egameview,
     estars, esteps, eshop, epotion, elevel, ecalore);

Nah perhatikan, setiap Entity dideklarasikan satu-persatu, kemudian akhirnya dimasukkan di dalam addEntity dan setiap variabelnya dipisahkan dengan koma.


2. drawEntityCollection
Method ini menggambarkan entity-entity yang sudah dimasukkan ke dalam  EntityCollection dari method addEntity di atas. Perhatikan contoh berikut. Kode ini berada dalam method onDraw yang ada dalam view:
  //  einfo.draw(c, cat);
  //  egameview.draw(c, cat);
  //  edistance.draw(c, cat);
  //  ehealthpoint.draw(c, cat);
  //  ebardistance.draw(c, cat);
  //  ebarhealth.draw(c, cat);
  //  estars.draw(c, cat);
  //  esteps.draw(c, cat);
  //  eshop.draw(c, cat);
  //  ecalore.draw(c, cat);
  //  epotion.draw(c, cat);
  //  elevel.draw(c, cat);
  drawEntityCollection(c, cat);

lihat, awalnya kita menggunakan einfo.draw(c,cat) dsb dsb dsb (yang diberi komentar). Sekarang cukup panggil drawEntityCollection(c,cat);

ingat, kamu harus memasukkan ke dalam EntityCollection apa saja entity yang akan didraw

3. RecycleEntityCollection
Nah, method ini yang mengembalikan agar memori bisa dipakai.
Method ini ditaruh di dalam kelas Activity dan ditaruh dalam method onStop. Perhatikan contoh berikut:

 @Override
 protected void onStop() {
  // TODO Auto-generated method stub
  super.onStop();
  
//  mu.ebardistance.recycle();  
//  mu.einfo.recycle();
//  mu.ebardistance.recycle();
//  mu.edistance.recycle();
//  mu.ehealthpoint.recycle();
//  mu.ebarhealth.recycle();
//  mu.egameview.recycle();
//  mu.estars.recycle();
//  mu.esteps.recycle();
//  mu.eshop.recycle();
//  mu.epotion.recycle();
//  mu.elevel.recycle();
//  mu.ecalore.recycle();
  //membebaskan memori
  mu.recycleEntityCollection();
 }
 
awalnya untuk melakukan recycle harus memanggil entity-entity yang ada di dalam view dan dipanggil recycle. Sekarang tinggal panggil mu.recycleEntityCollection(). mu adalah nama view yang digunakan oleh activity ini.

Kesimpulan

Jadi jangan lupa kalau mau bikin view yang ada entity-nya harus:
  1. Buat kelas entitynya
  2. Pastikan entity sudah memanggil resource
  3. Instansiasi entitynya di dalam View
  4. Masukkan entity-entity yang digunakan ke dalam EntityCollection di konstruktor menggunakan addEntity
  5. Draw dengan drawEntityCollection pada method onDraw
  6. Pada Activity, buat method yang Override onStop, panggil viewnya.recycleEntityCollection() agar tidak OutOfMemory
Sekian! Merepotkan juga ya? But it was a great fun coding journey though, hehe :D.

p.s: sekarang masih bermasalah dengan Thread nih, hm... selesaikan tampilan dulu lah ya~ Sudah deadline soalnya

No comments:

Post a Comment

Comment is caring :)