Tuval ve Yüzey kavramlarını anlama


114

Çizim sürecini SurfaceViewve dolayısıyla Android'de kullanılan tüm Surface/ Canvas/ Bitmapsistemi anlamakta zorlanıyorum .

Android geliştiriciler sitesinde bulabildiğim tüm makaleleri ve API dokümantasyon sayfalarını, birkaç android grafik öğreticisini, LunarLander kaynak kodunu ve bu soruyu okudum .

Lütfen bana bu ifadelerden hangilerinin doğru, hangilerinin doğru olmadığını ve nedenini söyleyin.

  1. Canvaskendine Bitmapbağlı. Surfacekendine Canvasbağlı.
  2. Tüm Viewpencereler aynı şeyi Surfacepaylaşır ve dolayısıyla aynı şeyi paylaşır Canvas.
  3. SurfaceViewait alt sınıfıdır Viewdiğerlerinden farklı olan, View'in alt sınıfları ve Viewkendisi, kendi sahip Surfaceçizmek için.

Ayrıca bir soru daha var:

  • Bitmap ile yüksek seviyeli işlemler için Surfacezaten varsa, neden bir sınıfa ihtiyaç var Canvas? Yapabilecek CanvasSurfaceyapmak için uygun olmayan bir duruma bir örnek verin .

2
Grafik mimarisi belgesi
fadden

Yanıtlar:


223

İşte bazı tanımlar:

  • Yüzey, ekranla birleştirilen pikselleri tutan bir nesnedir. Ekranda gördüğünüz her pencerenin (bir iletişim kutusu, tam ekran etkinliğiniz, durum çubuğu) içine çekildiği kendi yüzeyi vardır ve Surface Flinger bunları doğru Z sıralamasında son ekrana dönüştürür. Bir yüzeyde genellikle çift arabelleğe alınmış oluşturma yapmak için birden fazla arabelleğe (genellikle iki) sahiptir: uygulama, yüzey atıcı son arabelleği kullanarak ekranı birleştirirken, uygulamanın bitmesini beklemeye gerek kalmadan bir sonraki UI durumunu çizebilir çizim.

  • Bir pencere, temelde masaüstündeki bir pencereyi düşündüğünüz gibidir. Pencerenin içeriğinin görüntülendiği tek bir Yüzeye sahiptir. Bir uygulama, pencereler oluşturmak için Pencere Yöneticisi ile etkileşime girer; Pencere Yöneticisi her pencere için bir Yüzey oluşturur ve bunu çizim için uygulamaya verir. Uygulama Yüzeyde istediğini çizebilir; Pencere Yöneticisine göre bu sadece opak bir dikdörtgendir.

  • Görünüm, bir pencerenin içindeki etkileşimli bir UI öğesidir. Bir pencereye, pencerenin tüm davranışını sağlayan tek bir görünüm hiyerarşisi eklenir. Pencerenin yeniden çizilmesi gerektiğinde (bir görünümün kendisini geçersiz kılması gibi), bu, pencerenin Yüzeyine yapılır. Yüzey kilitlenir, bu da içine çizim yapmak için kullanılabilecek bir Kanvas verir. Hiyerarşide bir çizim geçişi yapılır ve her bir görünüm için UI'nin bir bölümünü çizmesi için Kanvas aşağıya verilir. Bir kez yapıldığında, Yüzey kilidi açılır ve yeni çizilen arabellek ön plana çıkarılır ve ardından Surface Flinger ile ekrana birleştirilir.

  • Bir SurfaceView, uygulamanın doğrudan çizim yapması için kendi özel Yüzeyini de oluşturan özel bir View uygulamasıdır (normal görünüm hiyerarşisinin dışında, aksi takdirde pencere için tek Yüzeyi paylaşması gerekir). Bunun çalışma şekli beklediğinizden daha basittir - tüm SurfaceView, pencere yöneticisinden yeni bir pencere oluşturmasını istemek, bu pencereyi SurfaceView penceresinin hemen arkasında veya önünde Z-düzenine söylemek ve eşleşecek şekilde konumlandırmaktır. SurfaceView içeren pencerede göründüğü yer. Yüzey ana pencerenin arkasına yerleştiriliyorsa (Z sırasına göre), SurfaceView ayrıca ana pencerenin bir bölümünü şeffaflıkla doldurur, böylece yüzey görülebilir.

  • Bir Bitmap, bazı piksel verilerine yönelik bir arayüzdür. Pikseller, doğrudan bir tane oluşturduğunuzda Bitmap tarafından tahsis edilebilir veya bir Tuvali çizim için bir Yüzeye bağlamak için dahili olarak ne olduğu gibi sahip olmadığı piksellere işaret ediyor olabilir. (Bir Bitmap oluşturulur ve Yüzeyin geçerli çizim arabelleğine işaret edilir.)

Ayrıca, bunun da işaret ettiği gibi, SurfaceView'ın oldukça ağır bir nesne olduğunu lütfen unutmayın. Belirli bir kullanıcı arayüzünde birden fazla SurfaceView varsa durun ve bunun gerçekten gerekli olup olmadığını düşünün. İkiden fazlasına sahipseniz, neredeyse kesinlikle çok fazla var demektir.


Çok teşekkür ederim! Cevap, işleri daha net hale getirdi. Yine de Canvas'ı Surface'a bağlamakla ilgili kısım belirsiz. Böyle bir operasyonun nerede gerekli olduğunu hayal edemiyorum. Bundan sonra bu işlemin bir örneği olabilir: LockCanvas () yöntemiyle SurfaceHolder'dan elde edilen, Tuval üzerine Bitmap çizme?
fyodorananiev

1
Çizim böyle olur Canvas, 2D çizim API'sidir. Bir yüzeye o çizecekseniz, ona çizim yapmak için Canvas 2d çizim API'sini kullanmak için tamponuna işaret eden bir Canvas yapmanız gerekir.
hackbod

6
#hackbod'sSurfaceViewView
Cevaba

47

Pencere, Yüzey, Tuval ve Bitmap'e kavramsal bir genel bakış

Pencere, Yüzey, Tuval ve Bitmap arasında etkileşimin nasıl gerçekleştiğine dair çok temel ve basit bir kavramsal genel bakış.
Bazen görsel bir temsil, çarpık kavramları anlamada çok yardımcı olur.
Umarım bu grafik birine yardımcı olabilir.


4
Görsel Görüntüler metinden daha iyidir: D
Maveň ツ

18

Bitmap, bir piksel koleksiyonu için basitçe bir sarmalayıcıdır. Bunu, diğer bazı kullanışlı işlevlere sahip bir piksel dizisi olarak düşünün.

Kanvas, tüm çizim yöntemlerini içeren sınıftır. Buna aşina iseniz, AWT / Swing'deki Graphics sınıfına benzer. Bir çemberin veya bir kutunun vb. Nasıl çizileceğine dair tüm mantık Canvas'ın içinde bulunur. Bir tuval, bir Bitmap veya açık bir GL konteyneri üzerine çizim yapar, ancak gelecekte diğer raster türlerine çizim yapmak için genişletilebilmesi için hiçbir neden yoktur.

SurfaceView, bir Yüzey içeren bir Görünümdür. Yüzey, bitmap'e benzer (bir piksel deposuna sahiptir). Nasıl uygulandığını bilmiyorum, ancak ekran görüntüleriyle doğrudan ilgili şeyler için ekstra yöntemler içeren bir tür Bitmap sarıcı olduğunu hayal ediyorum (Bu bir yüzeyin nedeni, bir Bitmap çok geneldir). Yüzeyinizden, temeldeki Bitmap ile ilişkilendirilmiş Tuvali gerçekten alan bir Tuval alabilirsiniz.

Sorularınız.

1.Canvas'ın kendisine eklenmiş kendi Bitmap'i vardır. Yüzeye eklenmiş kendi tuvali vardır.

Evet, bir tuval bir Bitmap (veya açık bir GL paneli) üzerinde çalışır. Surface size, Surface'ın Bitmap stili piksel deposu için kullandığı her neyse üzerinde çalışan bir Canvas sağlar.

2. Tüm pencere görünümleri aynı Yüzeyi paylaşır ve bu nedenle aynı Tuvali paylaşır.

Hayır. İstediğiniz kadar yüzey görünümüne sahip olabilirsiniz.

3. SurfaceView, View'in alt sınıfıdır ve diğer View'ın alt sınıflarından ve View'un kendisinden farklı olarak, çizilecek kendi Yüzeyine sahiptir.

Evet. ListView gibi, kendi List veri yapısına sahip bir View alt sınıfıdır. Her bir View alt sınıfı farklı bir şey yapar.


1
Öyleyse, Bitmapve Surfacesadece farklı piksel deposu türleri ve Canvasikisini de sarabilir mi?
fyodorananiev

2
Temelde evet. Canvas'ın bir yüzeye yazamaması dışında, Surface'ın kendi piksel deposu olarak kullandığı şey üzerinde çalışır (android kaynağına bakmadan ne olduğunu kesin olarak söyleyemem). Canvas yalnızca Bitmap ve GL için yapıcılar sağladığından, muhtemelen bir tür Bitmap uzantısıdır.
sksamuel

Harika yardım, teşekkürler! Cevap 2 hakkında 2. Sorumda SurfaceViews değil, standart görünümler demek istedim. Pek çok alan ve düğme içeren RelativeLayout'um olduğunu varsayalım. Bu durumda, Yüzey tüm pencereye bağlı mı ve görünüm hiyerarşisindeki tüm Görünümler tarafından paylaşılıyor mu?
fyodorananiev

1
Unutmayın ki Surface yalnızca bir piksel koleksiyonudur. Böylece her yüzey görünümünün kendi yüzeyi vardır ve her biri ekranın farklı bir bölümünde gösterilebilir. Ekranı doldurmaları gerekmez (tam ekran bir oyunda grafik oluşturmak için yaygın kullanım olmasına rağmen).
sksamuel

1
Bitmap ve Surface'ı gerçekten eşdeğer olarak düşünmezdim. Yüzey, pencere düzenleyicisi olan yüzey flinger'ın bildiği bir nesnedir. Yani, ekranda doğrudan görülebilen bir şeydir, ekranda Z sıralaması vardır vb.
hackbod
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.