之间有什么差异的各种方法以获得背景下?
-
06-07-2019 - |
题
各位卓代码,我已经看到:
public class MyActivity extends Activity {
public void method() {
mContext = this; // since Activity extends Context
mContext = getApplicationContext();
mContext = getBaseContext();
}
}
但是我找不到任何体面的解释是可取的,以及在什么情况下应使用。
指针的文件,指导关于什么可能打破,如果一个错误的选择,将不胜感激。
解决方案
我同意在Android中的上下文中文档很少,但您可以将来自不同来源的一些事实拼凑起来。
官方Google Android上的此博客文章开发人员博客主要是为了帮助解决内存泄漏,但也提供了一些关于上下文的好信息:
在常规Android应用程序中,您 通常有两种Context, 活动与应用。
进一步阅读文章,告诉我们两者之间的区别,以及何时可能要考虑使用应用程序Context( Activity.getApplicationContext()
)而不是使用Activity上下文此代码>)。基本上,应用程序上下文与应用程序相关联,并且在应用程序的整个生命周期中始终是相同的,因为活动上下文与活动相关联,并且可能会在屏幕方向更改期间销毁活动时多次销毁。这样
我找不到关于何时使用getBaseContext()的任何内容,而不是来自Dianne Hackborn的帖子,Dianne Hackborn是一位从事Android SDK工作的Google工程师:
不要使用getBaseContext(),只需使用 你拥有的语境。
这是来自 android-developers newsgroup ,您可能也想考虑在那里提出您的问题,因为在Android上工作的少数人实际监控该新闻组并回答问题。
总的来说,似乎最好尽可能使用全局应用程序上下文。
其他提示
以下是我发现的 context
的使用方法:
1)。在 Activity
本身中,使用 this
来扩展布局和菜单,注册上下文菜单,实例化小部件,启动其他活动,在 Activity
中创建新的 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);
开始活动
:
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)。对于Listeners和其他类型的Android类(例如ContentObserver),请使用上下文替换,如:
mContext = this; // Example 1
mContext = context; // Example 2
其中此
或 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)。对于Toasts,通常使用 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的框架开发人员那样使用 getBaseContext()
。
更新:添加上下文
用法的示例。
我几天前读过这个帖子,问自己同样的问题。我在阅读之后做出的决定很简单:始终使用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);
我注意到:如果你使用applicationContext实例化你的linearLayout,那么当你点击活动中的微调器时,你将有一个未捕获的异常来自dalvik虚拟机(不是来自你的代码,这就是为什么我有花了很多时间才找到我的错误......)。
如果您使用baseContext,那就没问题,上下文菜单将会打开,您可以在选择中进行选择。
所以这是我的结论:我想(我没有进一步测试过)比在Activity中处理contextMenu时需要baseContext ...
测试已经完成了API 8编码,并在HTC Desire,android 2.3.3上进行了测试。
我希望我的评论到目前为止并没有让你厌烦,并祝你一切顺利。快乐的编码; - )
首先,我同意尽可能使用appcontext。那么“这个”在活动中。我从来没有需要basecontext。
在我的测试中,在大多数情况下,它们可以互换。在大多数情况下,您希望获取上下文的原因是访问文件,首选项,数据库等。这些数据最终会反映为应用程序私有数据文件夹(/ data / data /)中的文件。无论您使用哪种上下文,它们都会映射到相同的文件夹/文件,这样您就可以了。
这就是我观察到的。也许有些情况你应该区分它们。
在某些情况下,在线程中运行某些内容时,您可以在应用程序上下文中使用Activity上下文。当线程完成执行并且您需要将结果返回给调用者活动时,您需要具有处理程序的上下文。
((YourActivity) context).yourCallbackMethod(yourResultFromThread, ...);
简单来说就是
getApplicationContext()
作为方法名称建议将使您的应用程序了解您可以从应用程序中的任何位置访问的应用程序范围的详细信息。所以你可以在服务绑定,广播注册等中使用它。应用程序上下文
将一直存在,直到应用程序退出。
getActivity()
或 this
将使您的应用了解当前屏幕,该屏幕也可以看到应用程序上下文提供的应用程序级别详细信息
。因此,无论您想了解当前屏幕如 Window
ActionBar
Fragementmanger
等,都可以使用此上下文。基本上和 Activity
扩展 Context
。这个上下文将一直存在,直到当前组件(活动)存活
在从 onClick
(非常绿色的菜鸟到Java和android)烘烤时,我只使用了这个和 getBaseContext
。当我的clicker直接在活动中并且必须在匿名内部点击器中使用 getBaseContext
时,我会使用它。我猜这是 getBaseContext
的诀窍,它可能会返回内部类隐藏的活动的上下文。
的混乱来源于这样的事实,有许多方式 访问方面,与(表面)没有明显的差异。以下是四个最常用的方法,你可能能够访问 下一个活动。
getContext()
getBaseContext()
getApplicationContext()
getActionBar().getThemedContext() //new
是什么语境? 我个人喜欢想的上下文作为国家的应用在任何给定的时间。该应用程序方面表示一个全球性的或基本结构的应用程序和活动或服务可以建立在它和代表结构的实例应用程序或传递国家。
如果你看一下源序。内容。背景下,你看到这方面是一个抽象的类和意见类如下:
接到全球信息有关的应用环境。这是一个抽象的级的执行提供由机器系统。它的
允许接入 application-specific
资源和课程,以及呼吁 application-level
操作,例如开展的活动、广播和接收的意图等。什么我从这是这方面提供了一个共同执行的访问水平应用以及系统一级的资源。应用程序的平衡资源可以访问东西像串资源 [getResources()]
或有资产 [getAssets()]
和系统级别的资源是任何东西,你的访问 Context.getSystemService().
事实上,看一看的评论意见的方法和他们似乎强化了这个理念:
getSystemService()
:返回来处理一个 system-level
服务名称。这类返回的对象不同而变化的要求的名称。getResources()
:返回的资源的实例应用程序的软件包。getAssets()
:返回的资源的实例应用程序的软件包。这可能是值得指出的是,在上下文摘要类,所有上述方法的抽象!仅一个实例getSystemService(Class)有一个执行和调用一个抽象的方法。这意味着,实现这些应当提供主要是通过实施课程,其中包括:
ContextWrapper
Application
Activity
Service
IntentService
看API文件,该层级的课程看起来像这样:
上下文
|—ContextWrapper
|——应用程序
|——ContextThemeWrapper
|————活动
|——服务
|———IntentService
因为我们知道, Context
本身没有提供任何了解,我们移向下树,看看的 ContextWrapper
并认识到,没有多少有的。由于申请延伸 ContextWrapper
, 没有什么好看过那里,因为它没有复盖的执行情况提供的 ContextWrapper
.这意味着实现为下文提供的操作系统和被隐藏在 API
.你可以看一下具体执行对上下文看来源ContextImpl类。