Maryam Dashtirahmatabadi
Maryam DashtirahmatabadiAndroid Developer @ Farazpardazan

Jak poprawnie korzystać z obiektu Context w Androidzie

Dowiedz się, czym jest Context w Androidzie i jak możesz z niego poprawnie korzystać.
29.04.20213 min
Jak poprawnie korzystać z obiektu Context w Androidzie

Context to jeden z najważniejszych obiektów w Androidzie - oznacza on kontekst obecnego stanu aplikacji i odpowiada za: 

  • Zdobywanie informacji dotyczących aktywności oraz aplikacji
  • Zdobywanie dostępu do bazy danych, zasobów dotyczących jakiejś aplikacji (potrzebny tekst, drawable itd.) oraz do klas, systemów plików i współdzielonych preferencji
  • Up-calls dla operacji na poziomie aplikacji, takich jak uruchamianie aktywności, broadcasting i otrzymywanie intencji (intents).


Jak widać, w Androidzie prawie wszystko musi mieć dostęp do obiektu Context. Jeśli użyjemy go w nieprawidłowy sposób, to możemy wywołać wyciek pamięci. Istnieją dwa typy obiektu Context:

  • Application Context: ten rodzaj obiektu Context jest ściśle powiązany z cyklem życia aplikacji. Oznacza to, że jeśli aplikacja nie została uśmiercona, to Context jest nadal dostępny. Zwykle jest to singleton, do którego dostęp można uzyskać z poziomu getApplicationContext(). Istotną rzeczą jest tutaj jednak to, że nie jest to kontekst związany z UI. Jeśli chcemy więc rozpocząć jakąś aktywność przy użyciu intencji, pokazania toasta lub czegokolwiek innego związanego z UI, to nawet jeżeli pobieramy, coś co będzie korzystać z motywów, to nie powinniśmy używać kontekstu aplikacji. Zauważ, że trzymanie referencji do aktywności w długo żyjącym obiekcie, czy wątku, może spowodować wyciek pamięci. W takim przypadku także wykorzystaj Context aplikacji. Oto lista funkcji Context w danej aplikacji: 

  1. Załaduj wartości zasobów
  2. Uruchom serwis
  3. Połącz z serwisem
  4. Wyślij transmisję
  5. Zarejestruj broadcastReceiver

  • Activity Context: ten rodzaj obiektu Context jest związany z cyklem życia aktywności. Można do niego uzyskać dostęp przez getContext(), jeśli activity nadal żyje. Z Activity Context powinno się korzystać, kiedy chcemy wywołać kontekst z obecnie działającego activity oraz z operacji związanych z UI - na przykład: 

  1. Załaduj wartości zasobów
  2. Stwórz layout
  3. Uruchom aktywność
  4. Pokaż dialog albo toast
  5. Uruchom serwis
  6. Połącz z serwisem
  7. Wyślij transmisję
  8. Zarejestruj broadcastReceiver


Oprócz getApplicationContext() i getContext(), to jako Context w Androidzie zauważysz jeszcze getBaseContext() oraz this. getBaseContext() to metoda ContextWrappera, która: 

Tworzy proxy implementacji obiektu Context, które deleguje wszystkie jego wywołania do innego kontekstu. Można stworzyć z niego podklasę, aby modyfikować zachowania bez zmieniania kontekstu oryginalnego. 


getBaseContext() pozwala nam na pobranie obecnego kontekstu znajdującego się wewnątrz ContexWrappera.

this odnosi się również do instancji klasy i można go używać, gdy Context jest potrzebny wewnątrz danego activity. Poniżej mamy kilka przypadków użycia, które wymagają obiektu Context korzystającego z Javy i Kotlina:

//if you want to start the activity from an activity, you should pass 'this' as context.
val intent = Intent(this, <YourClassname>::class.java)
startActivity(intent)


//view.getContext() refers to the current activity view. 
listView.setOnItemClickListener { parent, view, position, id -> 
    val myElement = adapter.getItemAtPosition(position) 
    val intent = Intent(view.getContext(), <YourClassname>::class.java)
    view.getContext().startActivity(intent)
}
public class ApplicationListAdapter extends RecyclerView.Adapter<
    ApplicationListAdapter.ApplicationListViewHolder> {
    ...
      
    @NonNull
    @Override
    public ApplicationListAdapter.ApplicationListViewHolder onCreateViewHolder(
        @NonNull ViewGroup parent, int viewType) {
        //the correct context can be inferred from the parent view as 'parent.getContext()' for inflation.
        View view = 
            LayoutInflater.from(parent.getContext())
            .inflate(R.layout.list_row_application, parent, false);
        return new ApplicationListViewHolder(view);
    }
    ...
      
    public class ApplicationListViewHolder extends RecyclerView.ViewHolder {
        private final ImageView mApplication_icon;

        public ApplicationListViewHolder(@NonNull View itemView) {
            super(itemView);

            mApplication_icon = itemView.findViewById(R.id.application_image);
        }

        private void bind(Application application) {
            //Context is needed outside of the onCreateViewHolder() method which is retrieved via 'itemView.getContext()'.
            Glide.with(itemView.getContext())
                    .load(application.getIcon())
                    .placeholder(R.mipmap.ic_launcher)
                    .into(mApplication_icon);

        }
    } 
    ...
}


Oryginał tekstu w języku angielskim możesz przeczytać tutaj.

<p>Loading...</p>