Як отримати контекст моєї діяльності?


76

Я насправді не розумію, як це все працює насправді, тому, якщо у мене є якийсь клас, Aякий потребує контексту класу, Bякий розширюється Activity, як мені отримати цей контекст?

Я шукаю більш ефективний спосіб, ніж надання контексту як параметра Aконструктору класів . Наприклад, якщо у класу Aбуде мільйони екземплярів, то в підсумку ми отримаємо мільйони надлишкових покажчиків, Contextтоді як ми повинні якось мати десь один і функцію отримання ...


4
classA. це ваш контекст діяльності.
Падма Кумар,

Але навіщо потрібен контекст у класі В?
Ракеш,

2
@Rakesh Ви помиляєтесь ... йому потрібен контекст B у класі A (який не поширює Activity). Це щось загальне.
Крістіан

Відповіді:


43

Ви можете використовувати Applicationклас (відкритий клас у пакеті android.application), тобто:

Базовий клас для тих, кому потрібно підтримувати глобальний стан програми. Ви можете надати власну реалізацію, вказавши її ім’я у тегу вашого AndroidManifest.xml, що призведе до створення цього класу для вас під час створення процесу для вашої програми / пакета.

Для використання цього класу виконайте:

public class App extends Application {

    private static Context mContext;

    public static Context getContext() {
        return mContext;
    }

    public static void setContext(Context mContext) {
        this.mContext = mContext;
    }

    ...

}

У вашому маніфесті:

<application
        android:icon="..."
        android:label="..."
        android:name="com.example.yourmainpackagename.App" >
                       class that extends Application ^^^

У діяльності B:

public class B extends Activity {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sampleactivitylayout);

        App.setContext(this);
                  ...
        }
...
}

У класі А:

Context c = App.getContext();

Примітка :

Зазвичай немає потреби в підкласі Application. У більшості ситуацій статичні одиночні можуть забезпечити ту саму функціональність більш модульним способом. Якщо ваш синглтон потребує глобального контексту (наприклад, для реєстрації широкомовних приймачів), функції для його отримання може бути наданий контекст, який внутрішньо використовує Context.getApplicationContext () при першій побудові сингтона.


4
Чи можу я запитати, навіщо йому потрібно реалізовувати OnInitListener?
akari

Крім того, оскільки ваш додаток, мабуть, має основну діяльність (моя названа MainActivity), ви можете помістити статичні Contextчлени в цей клас. (Тільки тому, що ви вже створили цей власний клас, тому немає необхідності створювати інший клас, додаток.) ​​З іншого боку, можливо, зрозуміліше вкладати речі, Appякі насправді не пов’язані MainActivity.
ToolmakerSteve

1
У будь-якому випадку, важливо встановити для статики значення null, коли клас B зникає. В іншому випадку цей екземпляр класу B, який може містити багато ресурсів, не буде GC’d до виходу вашої програми. (Якщо клас B є вашою основною діяльністю, і ви хочете зберігати його, поки ваш додаток не вийде , то ігноруйте цей коментар.)
ToolmakerSteve

3
Зберігання контекстів як статичних може спричинити витік пам’яті в Android.
Marc Bacvanski

OnInitListenerщо визначено TextToSpeech.OnInitListener?
Янос

54

Гаразд, я наведу невеликий приклад, як робити те, про що ти просиш

public class ClassB extends Activity
{

 ClassA A1 = new ClassA(this); // for activity context

 ClassA A2 = new ClassA(getApplicationContext());  // for application context. 

}

Дуже дякую! Це краще, ніж використання Applicationкласу.
Acuna

34

Найкращий і найпростіший спосіб отримати контекст діяльності - це поставити .thisназву назви. Наприклад: Якщо ім’я вашої активності - це SecondActivityконтекстSecondActivity.this


Цікаво, яка різниця між цим рішенням та більш складним прийнятим рішенням - якщо різниця взагалі існує.
Девід Гей

1
@DavidGay getApplicationContext повертає контекст для всієї програми, це не рекомендується використовувати, принаймні вам потрібно отримати контекст програми
Джон Олександр Беттс

@ John Alexander Betts Дякую! Це має бути прийнятою відповіддю і має набрати найбільшу кількість голосів. Це дуже проста і пряма відповідь, яка насправді відповідає на запитання ОП проти складного, незрозумілого та схильного до помилок рішення, яке було прийнято як відповідь.
пасигнатура

3

ви передаєте контекст класу B у його конструкторі та переконайтесь, що передаєте getApplicationContext () замість ActivityContext ()


2
applicationContext та контекст діяльності різні, вони мають різну тривалість життя, і ви повинні використовувати його відповідно.
Ган

@Gan залежить, що взагалі має сенс для класу B; я якось просто припускаю, що ApplicationContext буде кориснішим за контекст діяльності. але це лише я :)
Акула

@Shark: Контекст програми є лише частковим контекстом і не працює для деяких речей, зокрема для операцій, пов'язаних з користувацьким інтерфейсом.
Squonk

@Squonk ви можете назвати декілька? Я не стикався з випадком, коли контекст програми виходить з ладу, а контекст діяльності - ні.
Акула

2
@Shark: Вибачте, я це погано сформулював. Якщо вимога полягає лише у наявності, Contextтоді буде працювати або контекст програми, або контекст діяльності. Однак, якщо клас, що передається контекстом, є «допоміжним» класом, який може виконувати роботу, пов’язану з користувацьким інтерфейсом, тоді ctx.getWindowManager()(наприклад) не буде допустимим викликом методу, якщо ctxце посилання на контекст програми. Іншими словами, це справді залежить від того, чому класу потрібно передавати "контекст" і для чого він потрібен.
Squonk

2

Ви можете створити конструктор, використовуючи параметр Контекст класу A, тоді ви можете використовувати цей контекст.

Контекст c;

A (контекст контексту) {this.c = context}

З активності B ви створюєте об'єкт класу A, використовуючи цей конструктор та передаючи getApplicationContext ().


1

Якщо вам потрібен контекст A в B, вам потрібно передати його B, і ви можете зробити це, передавши Activity A як параметр, як пропонували інші. Я не бачу великої проблеми, щоб багато випадків, коли А мав власні вказівники на В, не впевнений, чи це буде навіть такою великою накладною витратою.

Але якщо в цьому проблема, можливо, зберегти вказівник на A як свого роду глобальний, доступний для Applicationкласу, як запропонував @hasanghaforian. Насправді, залежно від того, для чого вам потрібен контекст, ви навіть можете використовувати контекстApplication замість цього.

Я пропоную прочитати цю статтю про контекст, щоб краще зрозуміти, який контекст вам потрібен.


1
Оскільки це на рік пізніше прийнятої відповіді, яка вже детально показує, як це зробити, це не повинно бути окремою відповіддю: Єдиною «новою» частиною є останнє речення, яке містить корисне посилання . Це було б найкращим як коментар до прийнятої відповіді.
ToolmakerSteve

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.