SurfaceView dan GLSurfaceView

UI framework aplikasi Android didasarkan pada hierarki objek yang dimulai dengan View . Semua elemen UI melalui serangkaian pengukuran dan proses tata letak yang menyesuaikannya dengan area persegi panjang. Kemudian, semua objek tampilan yang terlihat dirender ke permukaan yang disiapkan oleh WindowManager saat aplikasi dibawa ke latar depan. Utas UI aplikasi melakukan tata letak dan rendering ke buffer per bingkai.

Tampilan Permukaan

SurfaceView adalah komponen yang dapat Anda gunakan untuk menyematkan lapisan komposit tambahan dalam hierarki tampilan Anda. SurfaceView mengambil parameter tata letak yang sama dengan tampilan lainnya, sehingga dapat dimanipulasi seperti tampilan lainnya, tetapi konten SurfaceView transparan.

Saat Anda merender dengan sumber buffer eksternal, seperti konteks GL atau dekoder media, Anda perlu menyalin buffer dari sumber buffer untuk menampilkan buffer di layar. Menggunakan SurfaceView memungkinkan Anda melakukannya.

Saat komponen tampilan SurfaceView akan terlihat, kerangka kerja meminta SurfaceControl untuk meminta permukaan baru dari SurfaceFlinger. Untuk menerima panggilan balik saat permukaan dibuat atau dihancurkan, gunakan antarmuka SurfaceHolder . Secara default, permukaan yang baru dibuat ditempatkan di belakang permukaan UI aplikasi. Anda dapat mengganti urutan Z default untuk menempatkan permukaan baru di atas.

Rendering dengan SurfaceView bermanfaat dalam kasus di mana Anda perlu merender ke permukaan yang terpisah, seperti saat Anda merender dengan Camera API atau konteks OpenGL ES. Saat Anda merender dengan SurfaceView, SurfaceFlinger 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 ekstra. Setelah merender dengan SurfaceView, gunakan utas UI untuk berkoordinasi dengan siklus hidup aktivitas dan buat penyesuaian pada ukuran atau posisi tampilan jika diperlukan. Kemudian, Komposer Perangkat Keras memadukan UI aplikasi dan lapisan lainnya.

Permukaan baru adalah sisi produsen BufferQueue, yang konsumennya adalah lapisan SurfaceFlinger. Anda dapat memperbarui permukaan dengan mekanisme apa pun yang dapat mengumpankan BufferQueue, seperti fungsi Canvas yang disediakan permukaan, memasang EGLSurface dan menggambar di permukaan dengan GLES, atau mengonfigurasi dekoder media untuk menulis permukaan.

SurfaceView dan siklus hidup aktivitas

Saat menggunakan SurfaceView, render permukaan dari utas selain utas UI utama.

Untuk aktivitas dengan SurfaceView, ada dua mesin status terpisah namun saling bergantung:

  • Aplikasi onCreate / onResume / onPause
  • Permukaan dibuat/diubah/dihancurkan

Saat aktivitas dimulai, Anda mendapatkan panggilan balik dalam urutan ini:

  1. onCreate()
  2. onResume()
  3. surfaceCreated()
  4. surfaceChanged()

Jika Anda mengklik kembali, Anda mendapatkan:

  1. onPause()
  2. surfaceDestroyed() (dipanggil tepat sebelum permukaan hilang)

Jika Anda memutar layar, aktivitas dirobohkan dan dibuat ulang dan Anda mendapatkan siklus penuh. Anda dapat mengetahui bahwa ini adalah restart cepat dengan memeriksa isFinishing() . Dimungkinkan untuk memulai/menghentikan aktivitas dengan sangat cepat sehingga surfaceCreated() terjadi setelah onPause() .

Jika Anda mengetuk tombol daya untuk mengosongkan layar, Anda hanya mendapatkan onPause() tanpa surfaceDestroyed() . Permukaan tetap aktif, dan rendering dapat dilanjutkan. Anda dapat terus mendapatkan acara Koreografer jika Anda terus memintanya. Jika Anda memiliki layar kunci yang memaksa orientasi berbeda, aktivitas Anda dapat dimulai ulang saat perangkat tidak kosong. Jika tidak, Anda bisa keluar dari layar kosong dengan permukaan yang sama seperti sebelumnya.

Masa pakai utas dapat diikat ke permukaan atau ke aktivitas, tergantung pada apa yang Anda inginkan terjadi saat layar menjadi kosong. Utas dapat memulai/menghentikan baik pada aktivitas mulai/berhenti atau di permukaan buat/hancurkan.

Memiliki utas mulai/berhenti pada Aktivitas mulai/berhenti berfungsi dengan baik dengan siklus hidup aplikasi. Anda memulai utas penyaji di onResume() dan menghentikannya di onStop() . Saat membuat dan mengonfigurasi utas, terkadang permukaan sudah ada, terkadang tidak (misalnya, masih aktif setelah mengaktifkan layar dengan tombol daya). Anda harus menunggu permukaan dibuat sebelum menginisialisasi di utas. Anda tidak dapat menginisialisasi dalam callback surfaceCreate() karena tidak akan diaktifkan lagi jika permukaan tidak dibuat ulang. Sebagai gantinya, buat kueri atau cache status permukaan, dan teruskan ke utas penyaji.

Membuat/menghentikan utas di permukaan membuat/menghancurkan berfungsi dengan baik karena permukaan dan penyaji saling terkait secara logis. Anda memulai utas setelah permukaan dibuat, yang menghindari beberapa masalah komunikasi antar utas; dan pesan yang dibuat/diubah di permukaan hanya diteruskan. Untuk memastikan bahwa rendering berhenti saat layar menjadi kosong dan dilanjutkan saat tidak kosong, beri tahu Koreografer untuk berhenti memanggil panggilan balik gambar bingkai. onResume() melanjutkan panggilan balik jika utas penyaji sedang berjalan. Namun, jika Anda menganimasikan berdasarkan waktu yang telah berlalu di antara bingkai, mungkin ada celah besar sebelum acara berikutnya tiba; menggunakan pesan jeda/lanjutkan yang eksplisit dapat mengatasi masalah ini.

Kedua opsi, apakah masa pakai utas terkait dengan Aktivitas atau permukaan, fokus pada bagaimana utas penyaji dikonfigurasi dan apakah itu dijalankan. Masalah terkait adalah mengekstraksi status dari utas saat aktivitas dihentikan (dalam onStop() atau onSaveInstanceState() ); dalam kasus seperti itu, mengikat masa pakai utas ke aktivitas berfungsi paling baik karena setelah utas penyaji digabungkan, status utas yang dirender dapat diakses tanpa primitif sinkronisasi.

Tampilan GLSurface

Kelas GLSurfaceView menyediakan kelas pembantu untuk mengelola konteks EGL, komunikasi antar utas, dan interaksi dengan siklus hidup aktivitas. Anda tidak perlu menggunakan GLSurfaceView untuk menggunakan GLES.

Misalnya, GLSurfaceView membuat utas 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 kebanyakan kasus, GLSurfaceView dapat membuat bekerja dengan GLES lebih mudah. Dalam beberapa situasi, itu bisa menghalangi.