UI framework aplikasi Android didasarkan pada hierarki objek yang dimulai dengan View. Semua elemen UI menjalani serangkaian pengukuran dan proses tata letak yang menyesuaikannya ke dalam area persegi panjang. Kemudian, framework merender semua objek tampilan yang terlihat ke permukaan yang disiapkan oleh WindowManager saat aplikasi dibawa ke latar depan. Thread UI aplikasi melakukan tata letak dan rendering ke buffer per frame.
SurfaceView
SurfaceView adalah komponen yang dapat Anda gunakan untuk menyematkan lapisan komposit tambahan dalam hierarki tampilan Anda. SurfaceView menggunakan parameter tata letak yang sama dengan tampilan lain, sehingga dapat dimanipulasi seperti tampilan lainnya, tetapi konten SurfaceView transparan.
Saat merender dengan sumber buffer eksternal, seperti konteks GL atau dekoder media, Anda perlu menyalin buffer dari sumber buffer untuk menampilkan buffer di layar. Anda dapat melakukannya dengan menggunakan SurfaceView.
Saat komponen tampilan SurfaceView akan terlihat, framework meminta SurfaceControl untuk meminta permukaan baru dari SurfaceFlinger. Untuk menerima callback saat permukaan dibuat atau dihancurkan, gunakan antarmuka SurfaceHolder. Secara default, framework menempatkan permukaan yang baru dibuat di belakang permukaan UI aplikasi. Anda dapat mengganti pengurutan Z default untuk menempatkan platform baru di paling atas.
Rendering dengan SurfaceView bermanfaat dalam kasus saat Anda perlu merender ke platform terpisah, seperti saat Anda merender dengan Camera API atau konteks OpenGL ES. Saat Anda merender dengan SurfaceView, SurfaceFlinger secara langsung menyusun buffer ke layar. Tanpa SurfaceView, Anda perlu menggabungkan buffer ke permukaan di luar layar, yang kemudian digabungkan ke layar, sehingga rendering dengan SurfaceView menghilangkan pekerjaan tambahan. Setelah merender dengan SurfaceView, gunakan thread UI untuk berkoordinasi dengan siklus proses aktivitas dan sesuaikan ukuran atau posisi tampilan jika diperlukan. Kemudian, Hardware Composer memadukan UI aplikasi dan lapisan lainnya.
Permukaan baru adalah sisi produsen BufferQueue, yang konsumennya adalah lapisan SurfaceFlinger. Anda dapat mengupdate platform dengan mekanisme apa pun yang dapat mengirimkan BufferQueue, seperti fungsi Canvas yang disediakan platform, melampirkan EGLSurface dan menggambar di platform dengan GLES, atau mengonfigurasi decoder media untuk menulis platform.
SurfaceView dan siklus proses aktivitas
Saat menggunakan SurfaceView, render permukaan dari thread selain thread UI utama.
Untuk aktivitas dengan SurfaceView, ada dua mesin status yang terpisah tetapi saling bergantung:
- Aplikasi
onCreate
/onResume
/onPause
- Permukaan dibuat/diubah/dihancurkan
Saat aktivitas dimulai, Anda akan mendapatkan callback dalam urutan ini:
onCreate()
onResume()
surfaceCreated()
surfaceChanged()
Jika Anda mengklik kembali, Anda akan mendapatkan:
onPause()
surfaceDestroyed()
(dipanggil tepat sebelum platform ditutup)
Jika Anda memutar layar, aktivitas akan dihentikan dan dibuat ulang, dan Anda
akan mendapatkan siklus penuh. Anda dapat mengetahui bahwa itu adalah mulai ulang cepat dengan memeriksa
isFinishing()
. Aktivitas dapat dimulai/dihentikan dengan sangat cepat
sehingga surfaceCreated()
terjadi setelah onPause()
.
Jika Anda mengetuk tombol daya untuk mengosongkan layar, Anda hanya akan mendapatkan
onPause()
tanpa surfaceDestroyed()
. Permukaan
tetap aktif, dan rendering dapat dilanjutkan. Anda dapat terus menerima
peristiwa Choreographer jika Anda terus memintanya. Jika Anda memiliki layar kunci yang memaksakan orientasi yang berbeda, aktivitas Anda mungkin dimulai ulang saat perangkat diaktifkan. Jika tidak, Anda dapat keluar dari layar kosong dengan
permukaan yang sama seperti sebelumnya.
Masa aktif thread dapat dikaitkan dengan platform atau aktivitas, bergantung pada apa yang ingin Anda lakukan saat layar menjadi kosong. Thread dapat dimulai/dihentikan pada saat Aktivitas dimulai/dihentikan atau saat pembuatan/penghancuran permukaan.
Memulai/menghentikan thread saat Aktivitas dimulai/dihentikan berfungsi baik dengan siklus proses aplikasi. Anda memulai thread perender di onResume()
dan menghentikannya di onStop()
. Saat membuat dan mengonfigurasi thread,
terkadang permukaan sudah ada, terkadang tidak (misalnya,
masih aktif setelah mengganti layar dengan tombol daya). Anda harus
menunggu hingga platform dibuat sebelum melakukan inisialisasi di thread. Anda tidak dapat
melakukan inisialisasi di callback surfaceCreate()
karena tidak akan diaktifkan
lagi jika platform tidak dibuat ulang. Sebagai gantinya, kueri atau cache status
platform, dan teruskan ke thread perender.
Memulai/menghentikan thread saat pembuatan/penghancuran platform berfungsi dengan baik karena platform dan perender saling terkait secara logis. Anda memulai thread
setelah platform dibuat, yang menghindari beberapa masalah komunikasi antar-thread; dan pesan yang dibuat/diubah platform akan diteruskan. Untuk memverifikasi bahwa rendering berhenti saat layar menjadi kosong dan dilanjutkan saat layar tidak kosong, beri tahu Choreographer untuk berhenti memanggil callback gambar frame. onResume()
melanjutkan callback jika thread perender sedang berjalan. Namun, jika Anda
menganimasikan berdasarkan waktu yang telah berlalu di antara frame, mungkin ada jeda yang besar sebelum
peristiwa berikutnya tiba; menggunakan pesan jeda/lanjutkan eksplisit dapat menyelesaikan
masalah ini.
Kedua opsi, baik masa aktif thread terkait dengan Aktivitas
atau platform, berfokus pada cara thread perender
dikonfigurasi dan apakah thread tersebut sedang dieksekusi. Masalah terkait adalah mengekstrak status
dari thread saat aktivitas dihentikan (di onStop()
atau
onSaveInstanceState()
); dalam kasus seperti itu, mengikat masa aktif
thread ke aktivitas akan berfungsi paling baik karena
setelah thread perender digabungkan, status thread yang dirender dapat
diakses tanpa primitif sinkronisasi.
GLSurfaceView
Class GLSurfaceView menyediakan class helper untuk mengelola konteks EGL, komunikasi antar-thread, dan interaksi dengan siklus proses aktivitas. Anda tidak perlu menggunakan GLSurfaceView untuk menggunakan GLES.
Misalnya, GLSurfaceView membuat thread untuk rendering dan mengonfigurasi konteks EGL di sana. Status dibersihkan secara otomatis saat aktivitas dijeda. Sebagian besar aplikasi tidak perlu mengetahui apa pun tentang EGL untuk menggunakan GLES dengan GLSurfaceView.
Dalam sebagian besar kasus, GLSurfaceView dapat mempermudah penggunaan GLES. Dalam beberapa situasi, hal ini dapat mengganggu.