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

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

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

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

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

Solutions Collecting From Web of "В чем разница между различными методами получения контекста?"

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

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

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

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

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

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

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

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

Вот что я нашел относительно использования 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() используйте 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 и т. Д.).

Замена контекста работы:

 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); } } } 

Inlined / Embedded 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() обычно используйте 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() как getBaseContext() разработчиками фреймворка Android.

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

Я прочитал эту тему несколько дней назад, задавая себе тот же вопрос. Мое решение после прочтения было простым: всегда используйте 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.

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

Во-первых, я согласен с тем, что мы должны использовать appcontext, когда это возможно. Затем «это» в деятельности. У меня никогда не было необходимости в basecontext.

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

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

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

 ((YourActivity) context).yourCallbackMethod(yourResultFromThread, ...); 

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

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

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

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