Какая разница между различными методами получения контекста?

В различных битах кода Android я видел:

 public class MyActivity extends Activity {
    public void method() {
       mContext = this;    // since Activity extends Context
       mContext = getApplicationContext();
       mContext = getBaseContext();
    }
 }

Однако я не могу найти подходящего объяснения, которое предпочтительнее и при каких обстоятельствах следует использовать.

Указатели на документацию по этому поводу и руководство о том, что может сломаться, если выбрано неправильное, будут очень оценены.

361
22 июня '09 в 15:38
источник поделиться
7 ответов

Я согласен с тем, что документация разрешена, когда дело доходит до контекстов в Android, но вы можете собрать несколько фактов из разных источников.

Это сообщение в блоге в официальном блоге разработчиков Google Android было написано в основном, чтобы помочь устранить утечки памяти, но также содержит некоторую полезную информацию о контекстах

В обычном приложении для Android вы обычно имеют два вида Контекста, Деятельность и применение.

Внимательно прочитав статью, мы расскажем о различии между этими двумя и когда вы захотите рассмотреть использование контекста приложения (Activity.getApplicationContext()) вместо использования контекста Activity this). В основном контекст приложения связан с Приложением и всегда будет одинаковым на протяжении всего жизненного цикла вашего приложения, где, поскольку контекст Activity связан с активностью и может быть многократно уничтожен по мере уничтожения активности во время изменений ориентации экрана и например.

Я не мог найти ничего о том, когда использовать getBaseContext(), кроме сообщения от Dianne Hackborn, одного из инженеров Google, работающих на Android SDK:

Не используйте getBaseContext(), просто используйте Контекст, который у вас есть.

Это было из сообщения в группе разработчиков Android-разработчиков, возможно, вам захочется рассмотреть вопрос и там, потому что несколько люди, работающие над Android, фактически контролируют эту группу новостей и отвечают на вопросы.

В общем случае предпочтительнее использовать глобальный контекст приложения, если это возможно.

291
22 июня '09 в 17:11
источник

Связанные вопросы


Похожие вопросы

Вот что я нашел относительно использования context:

1). В самом Activity используйте this для раздувания макетов и меню, регистрации контекстных меню, создания экземпляров виджета, запуска других действий, создания нового Intent в Activity, настройки экземпляров или другие методы, доступные в Activity.

Развертывание макета:

View mView = this.getLayoutInflater().inflate(R.layout.myLayout, myViewGroup);

Надувное меню:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    this.getMenuInflater().inflate(R.menu.mymenu, menu);
    return true;
}

Зарегистрировать контекстное меню:

this.registerForContextMenu(myView);

Создавать виджет:

TextView myTextView = (TextView) this.findViewById(R.id.myTextView);

Запустите Activity:

Intent mIntent = new Intent(this, MyActivity.class);
this.startActivity(mIntent);

Мгновенные настройки:

SharedPreferences mSharedPreferences = this.getPreferenceManager().getSharedPreferences();

2). Для класса приложения используйте getApplicationContext(), поскольку этот контекст существует для срока службы приложения.

Получить имя текущего пакета Android:

public class MyApplication extends Application {    
    public static String getPackageName() {
        String packageName = null;
        try {
            PackageInfo mPackageInfo = getApplicationContext().getPackageManager().getPackageInfo(getApplicationContext().getPackageName(), 0);
            packageName = mPackageInfo.packageName;
        } catch (NameNotFoundException e) {
            // Log error here.
        }
        return packageName;
    }
}

Привязать класс приложения:

Intent mIntent = new Intent(this, MyPersistent.class);
MyServiceConnection mServiceConnection = new MyServiceConnection();
if (mServiceConnection != null) {
    getApplicationContext().bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
}

3). Для прослушивателей и других типов классов Android (например, ContentObserver) используйте подстановку Context, например:

mContext = this;    // Example 1
mContext = context; // Example 2

где this или context - это контекст класса (Activity и т.д.).

Activity замена контекста:

public class MyActivity extends Activity {
    private Context mContext;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);        
        mContext = this;
    }
}

Подстановка контекста слушателя:

public class MyLocationListener implements LocationListener {
    private Context mContext;
    public MyLocationListener(Context context) {
        mContext = context;
    }
}

ContentObserver замена контекста:

public class MyContentObserver extends ContentObserver {
    private Context mContext;
    public MyContentObserver(Handler handler, Context context) {
        super(handler);
        mContext = context;
    }
}

4). Для BroadcastReceiver (включая встроенный/встроенный приемник) используйте собственный контекст получателя.

Внешний BroadcastReceiver:

public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();
        if (action.equals(Intent.ACTION_SCREEN_OFF)) {
            sendReceiverAction(context, true);
        }
        private static void sendReceiverAction(Context context, boolean state) {
            Intent mIntent = new Intent(context.getClass().getName() + "." + context.getString(R.string.receiver_action));
            mIntent.putExtra("extra", state);
            context.sendBroadcast(mIntent, null);
        }
    }
}

Встроенный/встроенный BroadcastReceiver:

public class MyActivity extends Activity {
    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final boolean connected = intent.getBooleanExtra(context.getString(R.string.connected), false);
            if (connected) {
                // Do something.
            }
        }
    };
}

5). Для служб используйте собственный контекст службы.

public class MyService extends Service {
    private BroadcastReceiver mBroadcastReceiver;
    @Override
    public void onCreate() {
        super.onCreate();
        registerReceiver();
    }
    private void registerReceiver() {
        IntentFilter mIntentFilter = new IntentFilter();
        mIntentFilter.addAction(Intent.ACTION_SCREEN_OFF);
        this.mBroadcastReceiver = new MyBroadcastReceiver();
        this.registerReceiver(this.mBroadcastReceiver, mIntentFilter);
    } 
}

6). Для тостов обычно используйте getApplicationContext(), но там, где это возможно, используйте контекст, переданный из Activity, Service и т.д.

Использовать контекст приложения:

Toast mToast = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG);
mToast.show();

Использовать контекст, переданный из источника:

public static void showLongToast(Context context, String message) {
    if (context != null && message != null) {
        Toast mToast = Toast.makeText(context, message, Toast.LENGTH_LONG);
        mToast.show();
    }
}

И, наконец, не используйте getBaseContext(), как сообщается разработчиками платформы Android.

UPDATE: Добавьте примеры использования context.

44
19 дек. '12 в 7:43
источник

Я прочитал эту тему несколько дней назад, задавая себе тот же вопрос. Мое решение после прочтения было простым: всегда используйте applicationContext.

Однако у меня возникла проблема с этим, я потратил несколько часов, чтобы найти его, и несколько секунд, чтобы его решить... (изменение одного слова...)

Я использую LayoutInflater, чтобы раздуть представление, содержащее Spinner.

Итак, вот две возможности:

1)

    LayoutInflater layoutInflater = LayoutInflater.from(this.getApplicationContext());

2)

    LayoutInflater layoutInflater = LayoutInflater.from(this.getBaseContext());

Затем я делаю что-то вроде этого:

    // managing views part
    View view = ContactViewer.mLayoutInflater.inflate(R.layout.aViewContainingASpinner, theParentView, false);
    Spinner spinner = (Spinner) view.findViewById(R.id.theSpinnerId);
    String[] myStringArray = new String[] {"sweet","love"};

    // managing adapter part
    // The context used here don't have any importance -- both work.
    ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this.getApplicationContext(), myStringArray, android.R.layout.simple_spinner_item);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(adapter);

    theParentView.addView(view);

Что я заметил: если вы создали экземпляр linearLayout с помощью applicationContext, тогда, когда вы нажмете на spinner в своей деятельности, у вас будет неперехваченное исключение, исходящее из виртуальной машины dalvik (а не из вашего кода, поэтому у меня есть потратил много времени, чтобы найти, где была моя ошибка...).

Если вы используете baseContext, тогда все в порядке, откроется контекстное меню, и вы сможете выбрать один из своих вариантов.

Итак, вот мой вывод: я полагаю (я еще не тестировал его дальше), чем baseContext требуется при работе с contextMenu в вашей деятельности...

Тест был выполнен с использованием API 8 и протестирован на HTC Desire, Android 2.3.3.

Надеюсь, мой комментарий до сих пор вас не утомляет, и желаю вам всего наилучшего. Счастливое кодирование; -)

12
06 янв. '12 в 20:14
источник

Во-первых, я согласен с тем, что мы должны использовать appcontext, когда это возможно. затем "this" в действии. Я никогда не нуждался в basecontext.

В моих тестах в большинстве случаев они могут быть взаимозаменяемы. В большинстве случаев причиной, по которой вы хотите получить контекст, является доступ к файлам, настройкам, базе данных и т.д. Эти данные в конечном итоге отражаются как файлы в папке личных данных приложения (/data/data/). Независимо от того, какой контекст вы используете, они будут сопоставлены с одной и той же папкой/файлами, чтобы вы были в порядке.

То, что я наблюдал. Возможно, есть случаи, когда вы должны их отличать.

6
20 марта '10 в 11:48
источник

В некоторых случаях вы можете использовать контекст Activity по контексту приложения при запуске чего-либо в потоке. Когда поток завершает выполнение и вам нужно вернуть результат обратно к активности вызывающего, вам нужен этот контекст с обработчиком.

((YourActivity) context).yourCallbackMethod(yourResultFromThread, ...);
3
25 сент. '10 в 2:29
источник

Простыми словами

getApplicationContext(), поскольку предлагаемое имя метода позволит вашему приложению узнать о подробностях приложения, доступ к которым вы можете получить из любого места приложения. Таким образом, вы можете использовать это в привязке к сервису, регистрации вещания и т.д. Application context будет оставаться до выхода приложения.

getActivity() или this сделает ваше приложение осведомленным о текущем экране, на котором видны также данные уровня приложения, предоставленные Application context. Итак, что бы вы ни хотели узнать о текущем экране, например Window ActionBar Fragementmanger, и поэтому доступны в этом контексте. В основном и Activity расширяем Context. Этот контекст будет живым до тех пор, пока не будет активен текущий компонент (активность)

2
09 февр. '17 в 15:49
источник

Я использовал только это и getBaseContext при поджаривании с onClick (очень зеленый noob для Java и Android). Я использую это, когда мой кликер находится непосредственно в действии и должен использовать getBaseContext в анонимном внутреннем клиенте. Я предполагаю, что это довольно трюк с getBaseContext, возможно, он возвращает контекст активности, в котором скрывается внутренний класс.

0
12 дек. '11 в 20:02
источник

Посмотрите другие вопросы по меткам или Задайте вопрос