获取Context的各种方法有什么区别?

在我看到的各种Android代码中:

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

但是我找不到任何合适的解释,哪一个更好,什么情况下应该使用。

指出这方面的文件,以及有关如果select了错误选项可能会破坏的指导,将不胜感激。

我同意文档在Android中的上下文是稀疏的,但你可以从各种来源拼凑一些事实。

这篇官方Google Android开发人员博客上的这篇博文主要是为了解决内存泄漏问题,但也提供了一些有关上下文的良好信息:

在一个普通的Android应用程序中,通常有两种Context,Activity和Application。

进一步阅读这篇文章讲述了两者之间的区别,以及何时您可能要考虑使用应用程序Context( Activity.getApplicationContext() )而不是使用Activity上下文)。 基本上,应用程序上下文与应用程序相关联,并且在应用程序的整个生命周期中始终保持相同,因为活动上下文与活动相关联,并且可能会多次销毁,因为活动在屏幕方向更改期间被销毁;这样。

我找不到什么时候使用getBaseContext(),而不是使用Dianne Hackborn(Google工程师在Android SDK上的工程师之一)的post:

不要使用getBaseContext(),只要使用你有的上下文。

这是来自android开发人员新闻组的一篇文章,您可能还想考虑在那里提出您的问题,因为less数在Android上工作的人员实际上会监视该新闻组并回答问题。

所以总体来说,如果可能,最好使用全局应用程序上下文。

以下是关于context的使用:

1)。 在一个Activity本身中,使用this来扩充布局和菜单,注册上下文菜单,实例化小部件,启动其他活动,在Activity创build新的Intent ,实例化首选项或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)。 对于监听器和其他types的Android类(例如ContentObserver),使用Contextreplace如:

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

这里或context是类(Activity等)的上下文。

Activity上下文replace:

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

监听器上下文replace:

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

ContentObserver上下文replace:

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

4)。 对于BroadcastReceiver (包括内联/embedded式接收器),使用接收器自己的上下文。

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

内嵌/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)。 对于Toast,通常使用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(); } } 

最后,不要像Android的框架开发人员所build议的那样使用getBaseContext()

更新:添加Context使用的例子。

我几天前看了这个post,问自己同样的问题。 读完这个之后,我的决定很简单:总是使用applicationContext。

但是,我遇到了这个问题,我花了几个小时find它,并花了几秒钟的时间来解决它…(改变一个字…)

我正在使用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); 

我注意到了:如果你用applicationContext实例化了linearLayout,那么当你点击你的活动中的微调器时,你将会有一个未被捕获的exception,来自dalvik虚拟机(不是来自你的代码,这就是为什么我花了很多的时间来find我的错误在哪里…)。

如果你使用baseContext,那么这是正确的,上下文菜单将打开,你将能够select你的select。

所以这里是我的结论:我想(我还没有进一步testing)比处理您的活动中的contextMenu需要baseContext …

testing已经完成了API 8的编码,并在HTC Desire,android 2.3.3上进行了testing。

我希望我的评论至今没有让你厌倦,祝你一切顺利。 快乐编码;-)

首先,我同意我们应尽可能使用appcontext。 然后在这个活动中“这个”。 我从来没有需要basecontext。

在我的testing中,大多数情况下可以互换。 在大多数情况下,您希望获取上下文的原因是访问文件,首选项,数据库等。这些数据最终会反映为应用程序专用数据文件夹(/ data / data /)中的文件。 无论您使用哪种上下文,它们都将映射到相同的文件夹/文件,因此您可以。

这就是我所观察到的。 也许有些情况下你应该区分它们。

在某些情况下,当在线程中运行某些东西时,您可以使用Activity上下文而非应用程序上下 当线程完成执行,你需要将结果返回给调用者的活动,你需要一个处理程序的上下文。

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

简而言之,

getApplicationContext()作为方法名称build议将使您的应用程序知道应用程序的广泛的细节,你可以从应用程序的任何地方访问。 所以你可以利用这个在服务绑定,广播注册等。 Application context将一直活着,直到应用程序退出。

getActivity()或者this会让你的应用程序知道当前屏幕,这也是应用application context提供的application context程序级别细节。 所以,无论你想了解当前的屏幕,如Window ActionBar Fragementmanger等都可用于此上下文。 基本上和Activity扩展Context 。 这个上下文将一直存在,直到当前的组件(活动)还活着

我只使用this和getBaseContextonClick (非常绿色的noob到Java和Android)敬酒。 当我的阅读器直接在活动中并且必须在匿名内部阅读器中使用getBaseContext时,我使用getBaseContext 。 我猜这几乎是getBaseContext的诀窍,它可能会返回内部类隐藏活动的上下文。