В чем разница между различными методами получения контекста?
в различных битах кода Android я видел:
public class MyActivity extends Activity {
public void method() {
mContext = this; // since Activity extends Context
mContext = getApplicationContext();
mContext = getBaseContext();
}
}
однако я не могу найти достойного объяснения что предпочтительнее, и при каких обстоятельствах, которые должны быть использованы.
указатели на документацию по этому вопросу и рекомендации о том, что может сломаться, если будет выбран неправильный, будут высоко оценены.
7 ответов:
Я согласен, что документация скудна, когда речь заходит о контекстах в Android, но вы можете собрать несколько фактов из разных источников.
этот блог на официальном блоге разработчиков Google Android было написано в основном, чтобы помочь устранить утечки памяти, но также предоставляет некоторую хорошую информацию о контекстах:
в обычном приложении для Android, вы обычно есть два вида контекста, Активность и Приложение.
чтение статьи немного дальше рассказывает о разнице между ними и когда вы можете рассмотреть возможность использования контекста приложения (
Activity.getApplicationContext()
) вместо того, чтобы использовать контекст действияthis
). В основном контекст приложения связан с приложением и всегда будет одинаковым на протяжении всего жизненного цикла вашего приложения, где, поскольку контекст действия связан с действием и может быть уничтожен много раз, как активность уничтожается во время изменения ориентации экрана и тому подобное.Я не мог найти действительно ничего о том, когда использовать getBaseContext () кроме сообщения от Дайан Хакборн, одного из инженеров Google, работающих на Android SDK:
не используйте getBaseContext (), просто используйте контекст у вас есть.
Это было с поста на группа новостей для android-разработчиков, вы можете рассмотреть возможность задать свой вопрос там, как ну, потому что горстка людей, работающих на Android, фактически контролирует эту группу новостей и отвечает на вопросы.
поэтому в целом кажется предпочтительным использовать глобальный контекст приложения, когда это возможно.
вот что я нашел относительно использования
context
:1) . внутри используйте
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);
Instantiate preferences:
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) используйте подстановку контекста, например:
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); } } }
Встроенный/Встроенный
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()
, но там, где это возможно, используйте контекст, переданный из действия, службы и т. д.использовать контекст приложения:
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.обновление: добавить примеры
Context
использование.
Я прочитал эту тему несколько дней назад, задавая себе тот же вопрос. Мое решение после прочтения этого было простым: всегда используйте applicationContext.
, я столкнулся с проблемой с этим, я потратил несколько часов, чтобы найти его, и несколько секунд, чтобы решить... (меняя одно слово...)Я использую LayoutInflater для раздувания представления, содержащего спиннер.
Так вот два возможности:
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, то при нажатии на счетчик в вашей деятельности у вас будет неперехваченное исключение, исходящее из виртуальной машины dalvik (не из вашего кода, поэтому я потратил много времени, чтобы найти, где была моя ошибка...).
Если вы используете baseContext, тогда все в порядке, откроется контекстное меню, и вы сможете выбрать один из ваших вариантов.
Итак, вот мой вывод: я полагаю (я не проверял его дальше), чем требуется baseContext при работе с contextMenu в вашей деятельности...
тест был сделан кодирование с API 8,и протестирован на HTC Desire, android 2.3.3.
Я надеюсь, что мой комментарий не скучно до сих пор, и желаю вам всего наилучшего. Счастливый кодирование ; -)
во-первых, я согласен, что мы должны использовать appcontext, когда это возможно. затем "это" в деятельности. у меня никогда не было необходимости basecontext.
в моих тестах, в большинстве случаев они могут быть заменены. В большинстве случаев причина, по которой вы хотите получить доступ к контексту, - это доступ к файлам, настройкам, базе данных и т. д. Эти данные в конечном итоге отражаются в виде файлов в папке личных данных вашего приложения (/data/data/). Независимо от того, какой контекст вы используете, они будут сопоставлены с той же папкой / файлами, что и вы ЛАДНО.
вот что я заметил. Может быть, есть случаи, которые вы должны различать их.
в некоторых случаях вы можете использовать контекст действия над контекстом приложения при запуске чего-то в потоке. Когда поток завершает выполнение, и вам нужно вернуть результат обратно в действие вызывающего, вам нужен этот контекст с обработчиком.
((YourActivity) context).yourCallbackMethod(yourResultFromThread, ...);
простыми словами
getApplicationContext()
как следует из названия метода, ваше приложение будет знать о широких деталях приложения, к которым вы можете получить доступ из любого места приложения. Таким образом, вы можете использовать это в привязке услуг, регистрации трансляции и т. д.Application context
будет жив, пока приложение не выйдет.
getActivity()
илиthis
сделает ваше приложение в курсе текущего экрана, который виден также детали уровня приложения, предоставляемыеapplication context
. Так что вы хотите знать о текущий экран какWindow
ActionBar
Fragementmanger
и так доступны с этим контекстом. В принципе иActivity
расширенияContext
. Этот контекст будет жив, пока текущий компонент (activity) не будет жив
Я только использовал это и
getBaseContext
когда тосты изonClick
(очень зеленый нуб для Java и android). Я использую это, когда мой кликер находится непосредственно в деятельности и должен использоватьgetBaseContext
в анонимном внутреннем кликере. Я предполагаю, что это в значительной степени трюк сgetBaseContext
, возможно, он возвращает контекст действия, в котором скрывается внутренний класс.