Soru Android'de 'Bağlam' nedir?


Android programcılığında tam olarak ne var? Context sınıf ve ne için kullanılır?

Bunu geliştirici sitesinde okudum, ancak bunu açıkça anlayamıyorum.


1581
2017-08-26 06:12


Menşei


İle ilgili bu soru - Christopher Perry
@ SourabSharma'nın mükemmel cevabına ek olarak (maalesef bu kabul edilmeyen bir şey değildir), bu blog yazısı Tek Sorumluluk İlkesi'nin prizmasıyla Bağlamı inceler: techyourchance.com/single-responsibility-principle - Vasiliy


Cevaplar:


Basitçe söylemek gerekirse:

Adından da anlaşılacağı gibi, uygulamanın / nesnenin mevcut durumu bağlamında. Yeni oluşturulmuş nesnelerin neler olduğunu anlamasına izin verir. Genellikle programınızın başka bir kısmı hakkında bilgi almak için bunu çağırırsınız (aktivite ve paket / uygulama).

İçeriği çağırarak alabilirsiniz getApplicationContext(), getContext(), getBaseContext() veya this (uzayan bir sınıfta ContextUygulama, Etkinlik, Hizmet ve IntentService sınıfları gibi).

Bağlamın tipik kullanımları:

  • Yeni nesneler oluşturma: Yeni görünümler, bağdaştırıcılar ve dinleyiciler oluşturma:

    TextView tv = new TextView(getContext());
    ListAdapter adapter = new SimpleCursorAdapter(getApplicationContext(), ...);
    
  • Standart ortak kaynaklara erişim: LAYOUT_INFLATER_SERVICE, SharedPreferences gibi hizmetler:

    context.getSystemService(LAYOUT_INFLATER_SERVICE)
    getApplicationContext().getSharedPreferences(*name*, *mode*);
    
  • Bileşenlere örtük olarak erişmek: İçerik sağlayıcılar, yayınlar, amaçlarla ilgili

    getApplicationContext().getContentResolver().query(uri, ...);
    

1244
2017-08-26 06:32



Örneğinde context.getSystemService(LAYOUT_INFLATER_SERVICE), nerede ve nasıl context tanımlanmış? - Dennis
Dinamik bir metin görünümü oluştururken bağlama neden ihtiyaç duyduğumuz iyi açıklandı. Ancak dinamik olarak metin dizileri oluştururken, herhangi bir bağlamdan bahsetmek zorunda değiliz. Neden böyle ? TextView [] textview = yeni TextView [10]; - Abhinav Arora
@AbhinavArora diziyi tanımlarken, aslında herhangi bir metin görünümünün bir örneğini oluşturmuyorsunuz (temelde sadece onların girmesi için alan yaratıyorsunuz). Bu diziye herhangi bir değer koymaya geldiğinizde, önceden oluşturulmuş TextView'lara ihtiyacınız olacak ya da bunları oluşturmanıza izin vermek için bir Bağlam gerekecek. - mc1arke
Görünümler neden içeriğe ihtiyaç duyar? Örneğin, TextView içeriğe sahip değilse ne yapamaz? - dinosaur
"Context" olmayan bir kod parçası, JVM'ye sahip her işletim sisteminde çalışabilir. Ancak bir bağlam varsa Android'de çalışmalıdır. Eğer Android'e özgü şeyleri kullanmak istiyorsanız (cihaz konumuna erişme, fotoğraf çekme, arka plan hizmeti çalıştırma gibi) bir bağlama ihtiyacınız var. http isteği. İçerik Java ve Android arasında bir köprü olarak kabul edilebilir. - Faruk Toptas


Bağlamın Tanımı ::

  • İçerik çevre verilerini temsil eder
  • Veritabanları gibi şeylere erişim sağlar

Daha basit terimler ::

  • Kişi-X'in bir başlangıç ​​yazılımı şirketinin CEO'su olduğunu düşünün.

  • Şirkette lider bir mimar var, bu lider mimar veritabanı, kullanıcı arayüzü gibi şirketteki tüm işleri yapar vb.

  • Şimdi CEO yeni bir Geliştirici tutuyor.

  • Yeni işe alınanların sorumluluğunu anlatan bir mimar. Yeni insanın yeteneklerine dayanarak kişi olup olmayacağı Veritabanı veya UI üzerinde çalışmak

Daha basit terimler ::

  • Android etkinliğinin uygulamanın kaynağına erişimi gibi.

  • Bir otele gittiğinizde kahvaltı, öğle yemeği ve uygun saatlerde akşam yemeği, değil mi?

  • Kaldığınız süre boyunca beğendiğiniz birçok şey var. Nasılsın bunları al

  • Oda servisini bu şeyleri senin için getirmesini rica et.

  • Burada oda servisi görevlisi, sizlerin Tek etkinlik ve otel sizin uygulamanız olacak, sonunda kahvaltı, öğle yemeği ve Akşam yemeği kaynak olmalı.


İçeriği içeren şeyler şunlardır:

  1. Bir kaynak yükleniyor.
  2. Yeni bir etkinlik başlatılıyor.
  3. Görünümler oluşturuluyor.
  4. sistem hizmeti almak.

Bağlam, temel sınıftır. Aktivite, Hizmet, Uygulama .... vb

Bunu açıklamanın başka bir yolu: İçeriği bir televizyon ve kanalın televizyonda uzak olarak ele alalım kaynaklar, hizmetler, niyetleri kullanma vs. - - - Burada uzaktan tüm farklı kaynaklara ön plana erişmek için bir erişim işlevi görür.

  • Yani, Uzaktan kaynakları, hizmetleri, niyetleri kullanarak vb gibi kanallara erişimi vardır.
  • Aynı şekilde… Uzaktan kumandayı herkesin erişimi, kaynakları, hizmetleri, amaçlarını kullanma, vb.

İçeriği alabileceğiniz farklı yöntemler

  • getApplicationContext()
  • getContext()
  • getBaseContext()
  • veya this (etkinlik sınıfında olduğunda)

Örnek:

TextView TV=new TextView(this);

this -> mevcut aktivitenin içeriğini ifade eder.


410
2017-08-20 05:25



Tamam, bu yüzden Faaliyetten türetilen sınıf bir bağlamın kendisi. Bu yüzden bunu yeni yaratılan görüşlere aktarmamızla, içeriği aktarıyoruz. - Oleg
Pek çok farklı yerden içeriğe erişebilmek için iyi bir tasarım kararı olup olmadığını merak ediyorum. Benim uygulamada bir statik getContext () yeterli olurdu. - Trilarion
@Trilarion ... Bağlamı nasıl kullanmak istediğinize bağlıdır getApplicationContext(), getContext(),getBaseContext() ..... Buna bakın -> (stackoverflow.com/a/10641257) - Devrath
Sadece bir metin görüntüsü oluşturarak son parçayı genişletmek için: Bazı durumlarda aramak gerekebilir SomeActivityName.this. Örnek için bir iş parçacığında this iş parçacığına değil faaliyete atıfta bulunur - Zoe


Kaynak


Android'de İçerik konusu birçok kişi için kafa karıştırıcı gibi görünüyor. İnsanlar, Android'de temel şeyleri yapmak için çoğunlukla Bağlamın gerekli olduğunu biliyorlar. İnsanlar bazen panikliyorlar, çünkü Bağlam gerektiren bazı işlemleri gerçekleştirmeye çalışıyorlar ve doğru Bağlamı “nasıl” alacağını bilmiyorlar. Android'deki İçerik fikrini tasvir etmeye çalışacağım. Sorunun eksiksiz bir şekilde ele alınması, bu yayının kapsamı dışındadır, ancak Genel bir bakış açısı sunmaya çalışacağım. Böylece, İçeriğin ne olduğu ve nasıl kullanılacağı hakkında bir fikriniz olacak. Bağlamın ne olduğunu anlamak için, kaynak koduna bir göz atalım:

https://github.com/android/platform_frameworks_base/blob/master/core/java/android/content/Context.java

Bağlam tam olarak nedir? 

Eh, belgelerin kendisi oldukça basit bir açıklama sağlar: Context sınıfı “bir uygulama ortamı hakkında küresel bilgi için bir arabirim” dir.

İçerik sınıfı, uygulaması Android işletim sistemi tarafından sağlanan soyut sınıf olarak bildirilmiştir. Dokümantasyon ayrıca, “… uygulamaya özel kaynaklara ve sınıflara erişim imkanlarının yanı sıra, aktiviteleri başlatma, yayınlama ve alma amaçları gibi uygulama seviyesindeki işlemlerin up-call'larına izin verir” de sağlar.

Şimdi çok iyi anlayabilirsiniz, neden, neden Bağlam. Çünkü bu sadece bu. Bağlam, bir Etkinlik, Hizmet veya herhangi bir başka bileşen için bağlantıyı veya kancayı sağlar, böylece sisteme bağlar ve küresel uygulama ortamına erişim sağlar. Başka bir deyişle: Bağlam, “genel olarak uygulama ile ilgili olarak hangi cehennemdeyim ve uygulamanın geri kalanıyla nasıl iletişim kurabilirim / iletişim kurabilirim?” Sorularının cevabını verir. Eğer bu durum biraz kafa karıştırıcı gibi görünüyorsa, hızlı Bağlam sınıfının maruz bıraktığı yöntemlere bakmak, onun gerçek doğası hakkında bazı ipuçları sağlar.

İşte bu yöntemlerden rastgele örnekleme:

  1. getAssets() 
  2. getResources()
  3. getPackageManager()
  4. getString()
  5. getSharedPrefsFile()

Bütün bu yöntemlerin ortak noktası nedir? Hepsi, uygulama çapında kaynaklara erişebilmek için Bağlamı kim erişime izin veriyorlar.

Başka bir deyişle, içerik, uygulama ortamının geri kalanına bir referansı olan bileşeni kancalar. Örneğin, bir Aktivite, Hizmet veya bu kaynaklara nasıl erişileceğini bilmesi şartıyla, örneğin, projenizdeki varlıklar (projenizdeki "düşünce / varlık" klasörü) uygulamada kullanılabilir. Aynı şey için de geçerli getResources() Böyle şeyler yapmak için izin verir getResources().getColor() sizi içine sokacak colors.xml kaynak (aapt'ın java kodu yoluyla kaynaklara erişmesini sağladığını, bunun ayrı bir sorun olduğunu).

Bu vesileymiş Context sistem kaynaklarına erişimi ve “daha ​​büyük uygulama” içerisindeki bileşenlerini kancalayan şeydir. Şimdi alt sınıflarına bakalım ContextÖzetin uygulanmasını sağlayan sınıflar Context sınıf. En belirgin sınıf Activity sınıf. Activitydan miras ContextThemeWrapper, hangi miras ContextWrapper, hangi miras Context kendisi. Bu sınıflar, şeyleri daha derin bir seviyede anlamak için faydalıdır, ancak şimdilik bunu bilmek yeterlidir. ContextThemeWrapper ve ContextWrapper sesleri tam olarak neye benziyorlar. Soyut unsurları uygularlar. Context Bir bağlamı (gerçek bağlamı) “sarar” ve bu işlevleri bu bağlama devrederek sınıflandırma.  Bir örnek faydalıdır - ContextWrapper sınıf, soyut yöntem getAssets itibaren Context sınıf aşağıdaki gibi uygulanır:

@Override
    public AssetManager getAssets() {
        return mBase.getAssets();
    }

mBase sadece kurucu tarafından belirli bir bağlama ayarlanmış bir alandır. Yani bir içerik sarılmış ve ContextWrapper getAssets yönteminin uygulanmasını söz konusu içeriğe atar. Şimdi incelemeye geri dönelim. Activity sonuçta miras kalan sınıf Context Bunun nasıl çalıştığını görmek için.

Muhtemelen bir Aktivitenin ne olduğunu biliyorsunuzdur, ancak gözden geçirme - temel olarak kullanıcının yapabileceği tek bir şeydir. Kullanıcının kullanıcı ile etkileşimde bulunduğu kullanıcı arayüzünü yerleştirmek için bir pencere sağlamaya özen gösterir. Diğer API'lere ve hatta geliştiricilere alışkın olmayan geliştiriciler, bunu bir "ekran" olarak nitelendirebilir. Bu, teknik olarak yanlıştır, ancak bizim amacımız için önemli değildir. Peki nasıl Activity ve Context etkileşim ve miras ilişkilerinde tam olarak neler oluyor?

Yine, belirli örneklere bakmak yararlıdır. Hepimiz Faaliyetleri nasıl başlatacağımızı biliyoruz. Faaliyete başladığınız “içeriği” sağlamanız şartıyla, sadece startActivity(intent)Niyet, bir Etkinlik başlattığınız bağlamı ve başlamak istediğiniz Etkinlik'i açıklar. Bu tanıdık startActivity(this, SomeOtherActivity.class).

Ve ne this? this Faaliyetiniz çünkü Activity sınıfından miras Context. Tam kepçe şu şekilde: Aradığınızda startActivitynihayetinde Activity sınıf böyle bir şey yürütür:

Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode);

Yani kullanır execStartActivity itibaren Instrumentation sınıf (aslında bir iç sınıftan Instrumentation denilen ActivityResult).

Bu noktada, sistem içlerine bir göz atmaya başlıyoruz.

Bu, işletim sisteminin gerçekten her şeyi ele aldığı yerdir. Enstrümantasyon Faaliyete tam olarak nasıl başlıyor? Peki, param this içinde execStartActivity Yukarıdaki yöntem sizin Faaliyetiniz, yani İçerik ve execStartActivity bu bağlamı kullanır.

30.000 genel bakış şöyledir: Enstrümantasyon sınıfı, çalışmasını yapmak için izlediği Etkinliklerin bir listesini izler. Bu liste tüm aktiviteleri koordine etmek ve faaliyet akışını yönetmek için her şeyin düzgün bir şekilde çalıştığından emin olmak için kullanılır.

İş parçacığı ve işlem konularını koordine edemediğim bazı işlemler var. Eninde sonunda ActivityResult yerel bir işlem kullanır - ActivityManagerNative.getDefault().startActivity() hangi kullanır Context aradığın zaman geçtiğin startActivity. Geçirdiğiniz içerik, gerektiğinde “niyet çözümü” ne yardımcı olmak için kullanılır. Niyet kararı, sistemin tedarik edilmediği takdirde niyetin hedefini belirleyebileceği süreçtir. (Daha fazla bilgi için kılavuza bakın).

Android'in bunu yapabilmesi için, tarafından sağlanan bilgilere erişim gerekir. Context. Özellikle, sistemin bir ContentResolver bu nedenle "niyetin verilerinin MIME türünü belirleyebilir". Bu tamamen hakkında biraz startActivity içeriğin kullanımını biraz karmaşık hale getirdi ve ben içselleri kendim tamamen anlamadım. Başlıca amacım, bir uygulama için gerekli olan işlemlerin çoğunu gerçekleştirmek için uygulama genelinde kaynakların nasıl erişilmesi gerektiğinin örneklerle açıklanmasıydı. Context Bu kaynaklara erişim sağlayan şeydir.  Daha basit bir örnek, Görüntüleme olabilir. Hepimiz özel bir Görünüm oluşturduğunuzu biliyoruz. RelativeLayout ya da başka View sınıf, bir alır bir kurucu sağlamalıdır Context bir argüman olarak. Özel Görünümünüzü başlattığınızda bağlamda geçersiniz.  Niye ya? Görünümün temalara, kaynaklara ve diğer Görünüm yapılandırma ayrıntılarına erişebilmesi gerektiğinden. Görünüm yapılandırma aslında harika bir örnektir. Her bir Bağlamın çeşitli parametreleri vardır. ContextEkranın boyutu veya yoğunluğu gibi şeyler için OS tarafından belirlenen uygulamalar. Görüntülemelerin ayarlanması için bu bilgilerin neden önemli olduğunu görmek kolaydır.

Son bir söz:  Bazı sebeplerden ötürü Android'e yeni giren insanlar (ve hatta yeni olmayanlar bile) Android'e geldiğinde nesne yönelimli programlamayı tamamen unutuyor gibi görünüyor. Bazı nedenlerden ötürü, insanlar Android gelişimlerini önceden tasarlanmış paradigmalara ya da öğrenilmiş davranışlara dönüştürmeye çalışırlar.

Android'in kendi paradigması ve önceden belirlenmiş kavramları bırakıp sadece dokümanları ve yönlendirme kılavuzunu okuduysa gerçekten tutarlı olan belirli bir kalıbı vardır. Ancak benim asıl amacım “doğru bağlamı elde etmek” bazen zor olabilirken, insanlar bağlamı gereği duymadıkları ve sahip olmadıklarını düşündükleri bir durumdan dolayı haksız bir şekilde panik yapıyorlar. Bir kez daha, Java bir miras tasarımı ile nesne yönelimli bir dildir.

Etkinliğinizin içeriğini "İçeriğe" sahipsiniz çünkü etkinliğinizin kendisi İçerik'ten miras kalıyor. Bunun için bir sihir yoktur (çeşitli parametrelerin ayarlanması ve içeriğinizi doğru bir şekilde “yapılandırmak için işletim sisteminin kendi başına yaptığı her şey hariç). Yani, bellek / performans sorunlarını bir kenara koyma (örneğin, bellekte, vb. Üzerinde olumsuz sonuçlara yol açacak şekilde veya buna ihtiyaç duymadan yaptığınız bağlamda referanslar bulundurmak), Bağlam, başkaları gibi bir nesnedir ve etrafından geçebilir. sadece herhangi bir POJO (Düz Eski Java Nesnesi) gibi. Bazen bu bağlamı almak için akıllıca şeyler yapmanız gerekebilir, ancak Nesnenin kendisinden başka hiçbir şeyden uzayan normal bir Java sınıfı, içeriğe erişimi olan bir şekilde yazılabilir; Bir bağlam alan ve daha sonra gerektiği şekilde o sınıfta kullanan bir kamu yöntemini ortaya çıkarmanız yeterlidir. Bu, İçerik veya Android içeriğinde kapsamlı bir tedavi olarak tasarlanmamıştı, ancak umarım İçerik'i biraz daraltmaya yardımcı olur.


258
2018-04-30 13:44



Bu mükemmel bir cevap. Herkesin sezgisel olarak bildiklerini söyleyen kabul edilenden çok daha iyi. - Honza Kalfus
aradığınız uzun cevap budur! iyi açıkladı - Nick Jian
Mükemmel ans! Ciddi anlamda ! - ZeekHuge
Hmmm, bana göre, eski zamanlayıcılar global değişkenleri çağırmak için kullanılan şeylere benziyor, bu da nesne yönelimi sahneye girdiğinde çok fazla kaşındı. - Ulf Edholm
Bu kabul edilen cevap olmalı. - AymenDaoudi


Bir Bağlam sisteme bir tanıtıcıdır; Kaynakların çözümlenmesi, veri tabanlarına ve tercihlere erişim elde etme, vb. gibi hizmetler sağlar. Bağlam, uygulamanızın şu anda çalışmakta olduğu ortamın bir tanıtıcısı gibidir. Activity nesnesi, Context nesnesini miras alır.

Daha fazla bilgi için Android Studio ile Android geliştirmeye giriş - Eğitici.


100
2017-08-26 06:33



Bağlantının içeriği değişmiş gibi görünüyor. Bölüm "5.8. Bağlam" ı deneyin. Ama orada fazla bilgi yok. - avenmore
Bu cevabı yazdığımdan beri 2 yıl geçti. Bölüm 5.4'e taşındı. Cevabımı yansıtacak şekilde güncelledim .. - giulio
Şimdi 7.4 olduğunu düşünüyorum. En az bir karakter olmasaydı cevabı düzenlerdim. - ecbrodie
Android için yeni sürümler çıktığında, yeni özellikler vb. Google doco'yu etrafında karıştırır. Güncelleme için teşekkürler. - giulio
"Bir Android uygulamasının etkinlikleri var" - Bu çizgi cevabınıza uymuyor. - Abhishek Jain


Zaten düşündüğün sürece, büyük düşün.

Bir uygulama ortamı hakkında global bilgiye arayüz. Bu, uygulaması Android sistemi tarafından sağlanan soyut bir sınıftır.

Uygulamaya özel kaynaklara ve sınıflara erişimin yanı sıra, aktiviteleri başlatma, yayınlama ve alma amaçları gibi uygulama düzeyinde işlemler için up-çağrısı sağlar.

Activity diagram


65
2017-12-28 08:05



Grafiği açıklayabilir misiniz yoksa aynı şeyi açıklayan bazı kaynakları paylaşır mısınız? - Prateek
Soru zaten cevaplandı. Grafiği takip etme fikri, Context sınıfının, Activity sınıfına yönlendiren büyük hiyerarşi yapısının başlangıç ​​noktası olduğunu göstermektir. - Dmytro Danylyk
Ben Prateek ile aynı fikirdeyim, grafikten bazı şeyler çıkarabiliyordum, herhangi bir referans ya da daha fazla açıklama yapmadan, bu grafik sadece ne olduğunu açıkça anlayanlara yardımcı oluyor. Context olduğunu. - Mike Williamson
Eh, bir dakika önce onları anlamayan biri olarak bana gerçekten yardımcı oldu. - Behrooz
Bu yanıltıcı bir cevaptır. İçeriğin ataları olmaktan çok daha çok İçerik var. Bir Bağlamın gerçekte ne olduğu hakkında hiçbir şey açıklamamanın yanı sıra, bu 'cevap', aynı zamanda İçerikler olan hizmetler ve uygulamaları unuttuğunuz için en fazla% 25'dir. - Tim Castelijns


ANDROID VE BAĞLAM

Çeşitli Android API'larına bakarsanız birçoğunun bir android.content.Context nesne olarak parametre. Ayrıca, bir Faaliyetin veya Hizmetin genellikle bir Bağlam. Bu, her iki sınıfın da Bağlam üzerinden genişlemesi nedeniyle çalışır.

Bağlam tam olarak nedir?

Android referans belgelerine göre, bu bir çeşitli çevre verilerini temsil eden varlık. Yerel erişim sağlar dosyalar, veritabanları, çevreye bağlı sınıf yükleyicileri, sistem düzeyinde hizmetler dahil olmak üzere hizmetler ve daha fazlası. Bu kitap boyunca ve gününüzde Android ile kodlanan gün, İçeriğin sık sık iletildiğini göreceksiniz. Kimden: "Uygulamada Android" kitabı.


57
2018-04-28 10:14





Bir Android bağlam bir arayüzey Uygulamaya özel kaynaklara ve uygulama ortamına ilişkin sınıf ve bilgilere erişim sağlar.

Android uygulamanız bir web uygulamasıysa   senin bağlamın bir şey olurdu   ServletContext benzer (burada tam bir karşılaştırma yapmıyorum)

Etkinlikleriniz ve hizmetleriniz ayrıca, uygulamanın çalıştığı ortam bilgilerine erişmek için tüm bu yöntemleri devraldığı sürece Bağlamı genişletir.


36
2017-08-26 06:40



Android 4.1'e göre AS Context, uygulama ortamına erişmek için çeşitli yöntemler sağlayan soyut bir sınıftır. - Rakesh
API Seviye 1 Bağlamından itibaren 4.1'den olmayan bir soyut sınıftır. - Sankar V
Bu soyut bir sınıf ... - Luis Pena
İnsanlar, "arayüz" diye alıntı yaptığımda java arayüzü demek istemiyorum ama arayüzey genel anlamda. - naikus
Açıkçası, bazı acemi sadece bir "arayüz" ne anlama geldiğini anlamıyor. Sadece bir java arayüzü olarak düşünürler. Referansları için bir link ekledim. Lütfen reddetmeden önce düşünün - naikus


Anlamak Basit Örnek context android'de:

Her patronun, daha az önemli ve zaman alan tüm görevleri yerine getirmek için bakması gereken bir asistanı vardır. Bir dosya ya da bir fincan kahve gerekirse, asistan çalışır. Bazı patronlar ofiste neler olduğunu neredeyse hiç bilmiyorlar, bu yüzden asistanlarına da bundan bahsediyorlar. Bazıları kendileri için çalışıyorlar ama diğer birçok şey için asistanlarının yardımına ihtiyaç duyuyorlar.

Bu senaryoda,

Boss - Android uygulamasıdır

Asistan - içeriğidir

Dosyalar / fincan kahve - kaynaklar

Uygulamamızın Etkinlikler, Uygulamalar vb. Gibi farklı bölümleri hakkında bilgi almamız gerektiğinde genel olarak içerik ararız.

Bağlamın yapıldığı bazı işlemler (asistanın gerekli olduğu şeyler):

Ortak kaynakları yükleme Dinamik görünümler oluşturma Tost mesajlarını görüntüleme Faaliyetleri başlatmak vb. İçeriği almanın farklı yolları:

getContext()

getBaseContext()

getApplicationContext()

this

26
2018-05-02 12:37