内容来自:http://www.devdiv.com/thread-27359-1-1.html
很多初入Android开发的网友向我们问到Context有什么作用,很多地方都用到它,这里Android123给这些新入门的网友做个简单的解释:
Context字面意思上下文,位于framework package的android.content.Context中,其实该类为LONG型,类似Win32中的Handle句柄,很多方法需要通过Context才能识别调用者的实例,比如说Toast的第一个参数就是Context,一般在Activity中我们直接用this代替,代表调用者的实例为Activity,而到了一个button的onClick(View view)等方法时,我们用this时就会报错,所以我们可能使用ActivityName.this来解决,主要原因是因为实现Context的类主要有Android特有的几个模型,Activity、Service以及BroadcastReceiver。
常规需要Context实例的方法主要有各种Service实现的类,比如说SensorManager在实例化时需要getSystemService(String)方法就必须由Context的实例执行,还有一些私有的文件系统I/O比如说openFileInput以及常用的Toast的makeText方法。
内容来自:http://blog.csdn.net/janronehoo/article/details/7348566
在android中常常会遇到与context有关的内容
浅论一下context : 在语句 AlertDialog.Builder builder = new AlertDialog.Builder(this); 中,要求传递的 参数就是一个context,在这里我们传入的是this,那么这个this究竟指的是什么东东呢? 这里的this指的是Activity.this,是这个语句所在的Activity的this,是这个Activity 的上下文。网上有很多朋友在这里传入this.getApplicationContext(),这是不对的。 AlertDialog对象是依赖于一个View的,而View是和一个Activity对应的。 于是,这里涉及到一个生命周期的问题,this.getApplicationContext()取的是这个应 用程序的Context,Activity.this取的是这个Activity的Context,这两者的生命周期是不同 的,前者的生命周期是整个应用,后者的生命周期只是它所在的Activity。而AlertDialog应 该是属于一个Activity的,在Activity销毁的时候它也就销毁了,不会再存在;但是,如果传 入this.getApplicationContext(),就表示它的生命周期是整个应用程序,这显然超过了它 的生命周期了。 所以,在这里我们只能使用Activity的this。
new AlertDialog.Builder(getApplicationContext())时发生错误:
E/AndroidRuntime(5844): android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
于是查了查:
getApplicationContext() 生命周期是整个应用,应用摧毁它才摧毁 Activity.this的context属于activity ,activity 摧毁他就摧毁
activity.this要返回一个activity,而getApplicationContext()就不一定返回一个activity
getApplicationContext() 返回应用的上下文,生命周期是整个应用,应用摧毁它才摧毁
Activity.this的context 返回当前activity的上下文,属于activity ,activity 摧毁他就摧毁
getBaseContext()
内容来自:http://liaowb1234.blog.163.com/blog/static/7715554720106911396569/
在android中context可以作很多操作,但是最主要的功能是加载和访问资源。
在android中有两种context,一种是 application context,一种是activity context,通常我们在各种类和方法间传递的是activity context。
比如一个activity的onCreate:
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this); //传递context给view control
label.setText("Leaks are bad");
setContentView(label);
}
把activity context传递给view,意味着view拥有一个指向activity的引用,
进而引用activity占有的资源:view hierachy, resource等。
这样如果context发生内存泄露的话,就会泄露很多内存。
这里泄露的意思是gc没有办法回收activity的内存。
Leaking an entire activity是很容易的一件事。
当屏幕旋转的时候,系统会销毁当前的activity,保存状态信息,再创建一个新的。
比如我们写了一个应用程序,它需要加载一个很大的图片,我们不希望每次旋转屏 幕的时候都销毁这个图片,
重新加载。实现这个要求的简单想法就是定义一个静态的Drawable,这样Activity 类创建销毁它始终保存在内存中。
实现类似:
public class myactivity extends Activity {
private static Drawable sBackground;
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this);//context为This,意思指在这个Actvity中连接一个TextView?
label.setText("Leaks are bad");
if (sBackground == null) {
sBackground = getDrawable(R.drawable.large_bitmap);
}
label.setBackgroundDrawable(sBackground);//drawable attached to a view
setContentView(label);
}
}
这段程序看起来很简单,但是却问题很大。当屏幕旋转的时候会有leak(即gc没法销毁activity)。
我们刚才说过,屏幕旋转的时候系统会销毁当前的activity。但是当drawable和view关联后,drawable保存了view的 reference,
即sBackground保存了label的引用,而label保存了activity的引用。既然drawable不能销毁,它所直接引用和间接引用的都不能销毁,
这样系统就没有办法销毁当前的activity,于是造成了内存泄露。gc对这种类型的内存泄露是无能为力的。
避免这种内存泄露的方法是避免activity中的任何对象的生命周期长过activity,避免由于对象对 activity的引用导致activity不能正常被销毁。
我们可以使用application context。application context伴随application的一生,与activity的生命周期无关。
application context可以通过Context.getApplicationContext或者Activity.getApplication方法获取。
避免context相关的内存泄露,记住以下几点:
1. 不要让生命周期长的对象引用activity context,即保证引用activity的对象要与activity本身生命周期是一样的
2. 对于生命周期长的对象,可以使用application context
3. 避免非静态的内部类,尽量使用静态类,避免生命周期问题,注意内部类对外部对象引用导致的生命周期变化
内容来自:http://blog.csdn.net/zhangqijie001/article/details/5891682
Context字面意思是上下文,位于framework package的android.content.Context中,其实该类为LONG型,
类似Win32中的Handle句柄。很多方法需要通过 Context才能识别调用者的实例:比如说Toast的第一个参数就是Context,
一般在Activity中我们直接用this代替,代表调用者的实例为Activity,而到了一个button的onClick(View view)等方法时,
我们用this时就会报错,所以我们可能使用ActivityName.this来解决,主要原因是因为实现Context的类主要有Android特有的几个模型,
Activity以及Service。
Context提供了关于应用环境全局信息的接口。它是一个抽象类,它的执行被Android系统所提供。
它允许获取以应用为特征的资源和类型。同时启动应用级的操作,如启动Activity,broadcasting和接收intents。
下面介绍Context的一些get方法,通过这些get方法可以获取应用环境全局信息:
1.public abstract Context getApplicationContext ()
Return the context of the single, global Application object of the current process.
2.public abstract ApplicationInfo getApplicationInfo ()
Return the full application info for this context's package.
3.public abstract ContentResolver getContentResolver ()
Return a ContentResolver instance for your application's package.
4.public abstract PackageManager getPackageManager ()
Return PackageManager instance to find global package information.
5.public abstract String getPackageName ()
Return the name of this application's package.
6.public abstract Resources getResources ()
Return a Resources instance for your application's package.
7.public abstract SharedPreferences getSharedPreferences (String name, int mode)
Retrieve and hold the contents of the preferences file 'name', returning a SharedPreferences through which you can retrieve and modify its values.
Only one instance of the SharedPreferences object is returned to any callers for the same name, meaning they will see each other's edits as soon as they are made.
8.public final String getString (int resId)
Return a localized string from the application's package's default string table.
9.public abstract Object getSystemService (String name)
Return the handle to a system-level service by name. The class of the returned object varies by the requested name. Currently available names are:
还有很多有用的方法,具体不一一列举。详情请参考文档,反正Context很有用。
内容来自:http://blog.csdn.net/android_tutor/article/details/8026018
大家好,今天给大家分享一下Android里的Context的一些用法,以前经常有人在群里问我比如我在一个工具类里的某个方法,或者View里需要调用Context.但是工具类还有View里没有这个上下文怎么办?为了解决大家的疑问,为了解决大家的疑问,我今天写一个简单的Demo.让大家如何学好自如的用Context.想什么时候有Context,什么时候就有Context.
这里大致可以分为两种:一是传递Context参数,二是调用全局的Context.
其实我们应用启动的时候会启动Application这个类,这个类是在AndroidManifest.xml文件里其实是默认的
- <application
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- >
- <activity
- android:name=".ApplicationDemoActivity"
- android:label="@string/app_name" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
这个Application类是单例的,也就是说我们可以自己写个Application(比如名为:MainApplication)类,来代替默认的Applicaiton,这个类可以保存应用的全局变量,我们可以定义一个全局的Context.供外部调用.用法如下:
- package com.tutor.application;
- import android.app.Application;
- import android.content.Context;
- public class MainApplication extends Application {
- /**
- * 全局的上下文.
- */
- private static Context mContext;
- @Override
- public void onCreate() {
- super.onCreate();
- mContext = getApplicationContext();
- }
- /**获取Context.
- * @return
- */
- public static Context getContext(){
- return mContext;
- }
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- }
- }
我们需要在AndroidMainifest.xml把MainApplication注册进去(第10行代码):
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.tutor.application"
- android:versionCode="1"
- android:versionName="1.0" >
- <application
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- android:name=".MainApplication" >
- <activity
- android:name=".ApplicationDemoActivity"
- android:label="@string/app_name" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
- </manifest>
为了让大家更容易理解,写了一个简单的Demo.步骤如下:
第一步:新建一个Android工程ApplicationDemo,目录结构如下:
第二步:新建MainApplication.java,代码和上面一样我就不贴了.
第三步:新建一个工具类ToolsUtil.java,代码如下
- package com.tutor.application;
- import android.content.Context;
- import android.widget.Toast;
- /**
- * @author frankiewei.
- * 应用的一些工具类.
- */
- public class ToolUtils {
- /**
- * 参数带Context.
- * @param context
- * @param msg
- */
- public static void showToast(Context context,String msg){
- Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
- }
- /**
- * 调用全局的Context.
- * @param msg
- */
- public static void showToast(String msg){
- Toast.makeText(MainApplication.getContext(), msg, Toast.LENGTH_SHORT).show();
- }
- }
第四步:新建一个View命名为MainView.java就是我们Activity现实的View.代码如下:
- package com.tutor.application;
- import android.app.Activity;
- import android.content.Context;
- import android.util.AttributeSet;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.widget.Button;
- import android.widget.FrameLayout;
- /**
- * @author frankiewei.
- * 自定义的MainView.
- */
- public class MainView extends FrameLayout implements View.OnClickListener{
- private Context mContext;
- private Activity mActivity;
- /**
- * 参数Button.
- */
- private Button mArgButton;
- /**
- * 全局Button.
- */
- private Button mGlobleButton;
- /**
- * 退出Button.
- */
- private Button mExitButton;
- public MainView(Context context){
- super(context);
- setupViews();
- }
- public MainView(Context context, AttributeSet attrs) {
- super(context, attrs);
- setupViews();
- }
- private void setupViews(){
- //获取View的上下文.
- mContext = getContext();
- //这里将Context转换为Activity.
- 由于view在创建时需要给构造器传入一个context,这个context一般是activity,万一不是呢?
- mActivity = (Activity)mContext;
- LayoutInflater inflater = LayoutInflater.from(mContext);
- View v = inflater.inflate(R.layout.main, null);
- addView(v);
- mArgButton = (Button)v.findViewById(R.id.arg_button);
- mGlobleButton = (Button)v.findViewById(R.id.glo_button);
- mExitButton = (Button)v.findViewById(R.id.exit_button);
- mArgButton.setOnClickListener(this);
- mGlobleButton.setOnClickListener(this);
- mExitButton.setOnClickListener(this);
- }
- public void onClick(View v) {
- if(v == mArgButton){
- ToolUtils.showToast(mContext, "我是通过传递Context参数显示的!");
- }else if(v == mGlobleButton){
- ToolUtils.showToast("我是通过全局Context显示的!");
- }else{
- mActivity.finish();
- }
- }
- }
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <TextView
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="Welcome to frankie wei's blog."
- />
- <Button
- android:id="@+id/arg_button"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="传递Context参数"
- />
- <Button
- android:id="@+id/glo_button"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="全局的Context"
- />
- <Button
- android:id="@+id/exit_button"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="退出App"
- />
- </LinearLayout>
第五步:修改ApplicationDemoActivity.java,代码如下:
- package com.tutor.application;
- import android.app.Activity;
- import android.os.Bundle;
- public class ApplicationDemoActivity extends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- MainView mMainView = new MainView(this);
- setContentView(mMainView);
- }
- }
第六步:运行上述工程效果如下:
运行效果1 运行效果2---- 点击第一个按钮