Beherskelse af Android-kontekst

Kontekst i Android er en af ​​de mest anvendte og misbrugte objekter. Men de fleste af artiklerne på nettet fokuserer på definitionen af, hvad det er. Jeg kunne ikke finde en god ressource, der gav mig indsigt og hjalp mig med at forstå det større billede. Så jeg prøvede at forenkle tingene med denne artikel.

Forord

Min mission for denne artikel er at hjælpe dig med at mestre Android Context. Dette er et af de centrale emner i Android-udvikling, og næsten ingen udviklere bruger kontekst fuldstændigt og på den måde, den blev designet.

Jeg offentliggjorde oprindeligt denne artikel som en serie på fire indlæg på min hjemmeside. Hvis du er interesseret i at læse kapitel for kapitel, er du velkommen til at læse der.

Kom godt i gang

Har du nogensinde mødt dette spørgsmål: Hvad er forskellen på getContext(), this, getBaseContext(), og getApplicationContext()? Hvis ja, hjælper denne artikel med at afklare det meste af din forvirring.

Bemærk: Du skal kende det grundlæggende i Android-udvikling, som Aktivitet, Fragmenter, Broadcast-modtager og andre byggesten. Hvis du er en ny udvikler, der lige er begyndt på din rejse ind i Android-verdenen, er det måske ikke det bedste sted at begynde.

Hvad pokker er kontekst?

Lad os indse det, Kontekst er en af ​​de mest dårligt designede funktioner i Android API. Du kan kalde det ”Guds” objekt.

En Android-app eller APK-pakke (APK) er et bundt af komponenter. Disse komponenter er defineret i Manifest og består hovedsageligt af Activity (UI), Service (Background), BroadcastReceiver (Action), ContentProvider (Data) og Resources (images, strings etc).

Udvikleren kan vælge at udsætte disse komponenter for et system ved hjælp af et intention-filter. For eksempel: Send e-mail eller del billede. De kan også vælge kun at udsætte komponenterne for andre komponenter i deres app.

Tilsvarende var Android-operativsystemet også designet til at udsætte komponenter. Et par velkendte er WifiManager, Vibrator og PackageManager.

Kontekst er broen mellem komponenter. Du bruger den til at kommunikere mellem komponenter, instantere komponenter og få adgang til komponenter.

Dine egne komponenter

Vi bruger kontekst til at instantiere vores komponenter med Activity, Content Provider, BroadcastReceiver osv. Vi bruger det også til at få adgang til ressourcer og filsystemer.

Din komponent og en systemkomponent

Kontekst fungerer som et indgangspunkt til Android-systemet. Nogle velbrugte systemkomponenter er WifiManager, Vibrator og PackageManager. Du kan få adgang til WifiManager ved hjælp af context.getSystemService(Context.WIFI_SERVICE).

På samme måde kan du bruge kontekst til at få adgang til filsystemet dedikeret til din app som bruger i OS.

Din egen komponent og en anden komponents app-komponent

Kommunikation mellem dine egne komponenter og andre apps komponenter er næsten identisk, hvis du bruger intention-filter-tilgangen. Når alt kommer til alt er alle komponenter en lige stor borger i Android.

Et eksempel på en hensigt, der bruges til at sende e-mail, er nedenfor. Alle komponenter, der tilbyder denne hensigtshandling, vil blive serveret til brugeren, der kan vælge, hvad de skal bruge.

Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);

Resumé

Lad os være enige om, at alt i Android er en komponent. Kontekst er broen mellem komponenter. Du bruger den til at kommunikere mellem komponenter, instantere komponenter og få adgang til komponenter. Jeg håber, at definitionen nu er klar.

Forskellige typer sammenhæng

Der er mange måder, du kan få fat i konteksten ( dårligt design spottet ).

For det meste bruger vi et af følgende, når vi har brug for kontekst:

- Application instance as context- Activity - Instance of your activity (this) - getApplicationContext() in Activity - getBaseContext() in Activity- Fragment - getContext() in Fragment- View - getContext() in View- Broadcast Receiver - Context received in broadcast receiver- Service - Instance of your service (this) - getApplicationContext() in Service- Context - getApplicationContext() in Context instance

Jeg deler konteksttyper i to kategorier: UI Context og Non-UI Context . Denne skelnen hjælper dig med at forstå n-wayslidt bedre.

UI-kontekst

I virkeligheden er kun ContextThemeWrapper UI Context - hvilket betyder Context + Dit tema .

Aktivitet udvides ContextThemeWrapper. Dette er grunden til, at dine synspunkter er temaet, når du puster enhver XML op. Hvis du puster dit layout op med en ikke-UI-kontekst, bliver dit layout ikke temaet. Prøv det.

Når du bruger Aktivitet som pladsholder for Context, er du garanteret at bruge UI Context. Hvis du bruger getContext-metoden fra Fragment, bruger du indirekte Aktivitet (hvis du vedhæftede Fragment via fragmentManager i aktivitet).

Men view.getContext()er ikke garanteret at være UI-kontekst.

Hvis View blev instantificeret ved hjælp af Layout Inflater og bestået UI Context, får du UI Context tilbage. Men hvis det blev instantificeret ved ikke at passere UI Context, får du den anden kontekst tilbage.

UI Context- Activity - Instance of your activity (this)- Fragment - getContext() in Fragment- View - getContext() in View (if View was constructed using UI-Context)

Ikke-UI-kontekst

Alt undtagen UI-kontekst er ikke-UI-kontekst. Teknisk set er alt, hvad der ikke er ContextThemeWrapper, ikke-UI-kontekst.

Ikke-UI-kontekst er tilladt, gør næsten alt, hvad UI-Context kan gøre ( dårligt design spottet ). Men som vi påpegede ovenfor, mister du temaet.

Non-UI Context- Application instance as context- Activity - getApplicationContext() in Activity- Broadcast Receiver - Context received in broadcast receiver- Service - Instance of your service (this) - getApplicationContext() in Service- Context - getApplicationContext() in Context instance

Tip : Alle konteksttyper antages at være kortvarige undtagen applikationskontekst. Dette er den, du får fra din applikationsklasse eller ved at bruge getApplicationContext()metoden, når du har kontekstadgang.

Resumé

Vi har forenklet det lidt ved at sætte Context i to spande. UI Context er Context + Theming, og teknisk set kommer enhver klasse, som er en underklasse af, ContextThemeWrapperi denne spand. Ikke-UI-kontekst er alle andre typer kontekst.

Hvor skal man bruge hvad

The question arises: what will go wrong if you use context in the wrong place? Following are a few scenarios:

Scenario 1

Lets say you are inflating a layout and you use Non-UI Context. What may go wrong? You can guess in this case: you will not get a themed layout. Not so bad, hmm? It’s bearable.

Scenario 2

You pass UI-Context to someplace where all it needs is resource access or file system access. What can no wrong? Short Answer: Nothing. Remember, UI-Context = Context + Theme. It will gladly serve as context for you.

Scenario 3

You pass UI-Context to someplace where all it needs is resource access or file system access but it is a long operation in the background. Say downloading a file. Now what can go wrong? Short Answer: Memory leak.

If you are lucky and download completes quickly, the object is released and everything is fine. Sun is shining and birds are chirping. This is one of the most common mistakes developers make. They pass the reference of UI-Context to long living objects, and sometimes it has zero side effect.

However, sometimes Android wants to claim memory for either one of your next component’s requirements or another component’s requirements, and woooshhhh!!! You run out of memory in your app. Don’t worry, I will explain.

Memory Leak or Crash! That’s it.

Yes this is the worst case scenario when you use context in the wrong place. If you are new to the app development world, let me share some wisdom. Memory leaks are inversely proportional to your experience. Every Android developer has leaked memory. There is no shame in doing so.

Shame is when you repeat the mistake again and leak it the same way. If you leak memory a different way every time, congrats you are growing. I have explained what a Memory leak is with a short story here.

Okay I get it, but what is the relation of Context here?

Say it aloud, “Bad Design Spotted".

Almost everything in Android needs access to Context. Naive developers pass UI Context, because that’s what they have access to very easily. They pass short-living context (usually Activity context) to long living objects and before the memory/money is returned back to system, they hit a crisis. Woooshhh!!!

The simplest way to deal with this is with Async Task or Broadcast Receiver. But discussing them isn’t in the scope of this article.

Summary

  • Do you need to access UI related stuff? Use UI-Context. Inflating Views and showing dialogue are the two use cases I can think of.
  • Otherwise, Use Non UI Context.
  • Make sure you do not pass short-living context to long-living objects.
  • Pass knowledge, help people, plant trees and invite me for a coffee.

Tips and Tricks

What is the difference between this, getApplicationContext() and getBaseContext()?

This is one question every Android developer have encountered in their lives. I will try to simplify it as much as possible. Let’s take a step back and revisit the basics.

We know there are many factors in mobile devices. For instance, configuration changes all the time, and locale can change explicitly or implicitly.

All of these changes trigger apps to re-create so they can pick the right resources that are the best match to their current configuration. Portrait, Landscape, Tablet, Chinese, German, and so on. Your app needs the best possible resources to deliver the best user experience. It is the Context which is responsible for delivering those best match resources.

Try answering this question:

The user’s configuration is currently in portrait and you want to access landscape resources. Or the user locale is en and you want to access uk resources. How will you do it?

Below are some magical methods from Context:

There are many createX methods, but we are mainly interested in createConfigurationContext. Here is how you can use it:

Configuration configuration = getResources().getConfiguration();configuration.setLocale(your_custom_locale);context = createConfigurationContext(configuration);

You can get a hold of any type of Context you desire. When you call any method on the new Context you just got, you will get access to resources based on the configuration you had set.

I know it is amazing. You can send me thank you card.

Similarly, you can create a Themed Context and use it to inflate views with the theme you want.

ContextThemeWrapper ctw = new ContextThemeWrapper(this, R.style.YOUR_THEME);

Let’s come back to the tricky question we asked above and discuss Activity Context.

What is the difference between this, getApplicationContext()and getBaseContext()?

These are the possible ways you can get a hold on Context when you are in the Activity scope.

thispoints to Activity itself, our UI Context and short life context. getApplicationContext() points to your application instance which is Non-UI and long living context.

baseContext is the base of your Activity Context which you can set using a delegate pattern. You already know you can create Context with any xyz configuration you want. You can combine your xyz configuration knowledge with Base Context and your Activity will load resources as you desire.

Here is the method you can use:

@Overideprotected void attachBaseContext (Context base) {super.attachBaseContext(useYourCustomContext);}

Once BaseContext is attached, your Activity will delegate calls to this object. If you do not attach to Activity, it remains baseContext and you get Activity when you call getBaseContext.

Conclusion

We can say Context is the life of your android app. From Android’s point of view, it is your app. You can do almost nothing without Context. Without it, your app is plain Java code.

Context + Java code => Android

Good or bad, it is the design we have and we have to make the best of it. From the first part of this article, we learned that we use it to communicate between components, instantiate components, and access components.

In the next part, we learned that Context can be UI or NonUI, Short Lived or Long lived.

Following that, we learned that you need to choose context carefully otherwise you have to deal with memory leaks and other UI issues.

Finally, you saw that Context is responsible for loading best match resources for your app and you can configure it as you want. We also learned the difference between this, applicationContext and baseContext.

Many developers will advise you to use only application context. Do not use Application Context everywhere from the fear of a memory leak. Understand the root cause and always use the right Context in the right place.

You, my dear friend, are a master of Android Context now. You can suggest the next topic you want to understand. Click here to suggest.

Below are links from the original Series Mastering Android Contexton my blog.

Chapter 1

What the heck is Context? Why do we need it and what are various use cases in day to day development?

Chapter 2

Simplifying Context. We will discuss how many types of context are there and which ones are you suppose to use.

Chapter 3

Where to use UI Context and where to use Non UI-Context. How using context at wrong place may lead to memory leaks.

Chapter 4

Min brugergrænseflade-kontekst giver mig også flere forskellige sammenhængstyper. Lad os besvare dette spørgsmål og se, hvordan man undgår almindelige faldgruber.

Uddannelse

Ved du, at din app mange gange går ned, fordi dine udviklere ikke bruger Context korrekt? Lad os lære sammen. Jeg tilbyder træning i Android, Java og Git.

Vil du mestre Android-temaer? Tjek vores serie med mere end 3.000 opvoter.

Del gerne din feedback og spørgsmål. Glad kodning.

Følg mig på Medium og Twitter for opdateringer.