Android中的Context详解
16lz
2021-12-04
Android中的Context详解(2012-07-23 14:21) 标签: Android context 分类: android_context
Android基础概念Context的作用
android context理解
在android中context可以作很多操作,但是最主要的功能是加载和访问资源。在android中有两种context,一种是 application context,一种是activity context,通常我们在各种类和方法间传递的是activity context。 比如一个activity的onCreate:
这段程序看起来很简单,但是却问题很大。当屏幕旋转的时候会有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. 避免非静态的内部类,尽量使用静态类,避免生命周期问题,注意内部类对外部对象引用导致的生命周期变化
根据packageName构造Context
Android获取其他包的Context实例然后干坏事
Android基础概念Context的作用
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方法。
android context理解
在android中context可以作很多操作,但是最主要的功能是加载和访问资源。在android中有两种context,一种是 application context,一种是activity context,通常我们在各种类和方法间传递的是activity context。 比如一个activity的onCreate:
点击(此处)折叠或打开
- protected void onCreate(Bundle state) {
- super.onCreate(state);
- TextView label = newTextView(this);
- //传递context给view control
- label.setText("Leaks are bad");
- setContentView(label);
- }
点击(此处)折叠或打开
- publicclassmyactivityextendsActivity{
- privatestaticDrawable sBackground;
- protectedvoidonCreate(Bundlestate){
- super.onCreate(state);
- TextViewlabel=newTextView(this);
- 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. 避免非静态的内部类,尽量使用静态类,避免生命周期问题,注意内部类对外部对象引用导致的生命周期变化
根据packageName构造Context
通常情况下获取当前应用的context的方法是getApplicationContext, 但是通过根据其他的packageName如何构造 Context呢?Android平台的应用实例其实还可以通过其他方式构造。 比如代码:
点击(此处)折叠或打开
- try {
- Context ctx=createPackageContext("com.android123.Cwj", 0);
- //ctx已经是com.android123.cwj的实例
- } catch(NameNotFoundException e) {
- //可能由于 pacakgeName不存在所以必须处理该异常
- }
Android Context应该怎么写?
点击(此处)折叠或打开
- AlertDialog.Builder alert=newAlertDialog.Builder(this);
- alert.setTitle("Warning");
- alert.setMessage("Wrong time!");
- alert.show();
Android中Activity共享变量的另一方法:Application context
Android中在不同Activity中传递变量,通常使用Intent中Bundle添加变量的操作方法。
点击(此处)折叠或打开
- Intent intent=newIntent();
- intent.setClass(A.this,B.class);
- Bundle bundle=newBundle();
- bundle.putString("Info","Information");
- intent.putExtras(bundle);
- startActivity(intent);
- Intent intent=newIntent();
- intent.setClass(A.this,B.class);
- Bundle bundle=newBundle();
- bundle.putString("Info","Information");
- intent.putExtras(bundle);
- startActivity(intent);
-
点击(此处)折叠或打开
- classMyAppextendsApplication{
- privateStringmyState;
- publicStringgetState(){
- returnmyState;
- }
- publicvoidsetState(Strings){
- myState=s;
- }
- }
点击(此处)折叠或打开
- android:name=".MyApp"
- android:icon="@drawable/icon"
- android:label="@string/app_name">
点击(此处)折叠或打开
- classBlahextendsActivity{
- @Override
- publicvoidonCreate(Bundle b){
- ...
- MyApp appState=((MyApp)getApplicationContext());
- Stringstate=appState.getState(); ...
- }
- }
-
[小技巧]在任意位置获取应用程序Context - [Android学习笔记]
Android程序中访问资源时需要提供Context,一般来说只有在各种component中(Activity, Provider等等)才能方便的使用api来获取Context, 而在某些工具类中要获取就很麻烦了。为此,我们可以自定义一个Application类来实现这种功能。
点击(此处)折叠或打开
- importandroid.app.Application;
- publicclassMyApplicationextendsApplication{
- privatestaticMyApplication instance;
- publicstaticMyApplicationgetInstance(){returninstance;}
- @Override
- publicvoidonCreate(){
- // TODO Auto-generated method stub
- super.onCreate();
- instance=this;
- }
- }
Android获取其他包的Context实例然后干坏事
Android中有Context的概念,想必大家都知道。Context可以做很多事情,打开activity、发送广播、打开本包下文件夹和数据库、获取classLoader、获取资源等等。如果我们得到了一个包的Context对象,那我们基本上可以做这个包自己能做的大部分事情。 那我们能得到吗?很高兴的告诉你,能! Context有个createPackageContext方法,可以创建另外一个包的上下文,这个实例不同于它本身的Context实例,但是功能是一样的。 这个方法有两个参数: 1。packageName 包名,要得到Context的包名 2。flags 标志位,有CONTEXT_INCLUDE_CODE和CONTEXT_IGNORE_SECURITY两个选项。CONTEXT_INCLUDE_CODE的意思是包括代码,也就是说可以执行这个包里面的代码。CONTEXT_IGNORE_SECURITY的意思是忽略安全警告,如果不加这个标志的话,有些功能是用不了的,会出现安全警告。下面给个小例子,执行另外一个包里面的某个类的方法。 另外一个包的包名是chroya.demo,类名Main,方法名print,代码如下:
点击(此处)折叠或打开
- packagechroya.demo;
- importandroid.app.Activity;
- importandroid.os.Bundle;
- importandroid.util.Log;
- classMainextendsActivity{
- @Override
- publicvoidonCreate(Bundle savedInstanceState){
- super.onCreate(savedInstanceState);
- }
- publicvoidprint(Stringmsg){
- Log.d("Main","msg:"+msg);
- }
- }
点击(此处)折叠或打开
- Contextc=createPackageContext("chroya.demo",
- Context.CONTEXT_INCLUDE_CODE|Context.CONTEXT_IGNORE_SECURITY);
- //载入这个类
- Classclazz=c.getClassLoader().loadClass("chroya.demo.Main");
- //新建一个实例
- Objectowner=clazz.newInstance();
- //获取print方法,传入参数并执行
- Objectobj=clazz.getMethod("print",String.class).invoke(owner,"Hello");
-
更多相关文章
- 《Android(安卓)群英传》 阅读笔记 第四章~第六章
- onEditorAction不执行
- Android(安卓)NDK 的学习之旅-----JNI LOG 打印
- Android(安卓)Firebase Dynamic Links 动态链接使用心得
- Android基本控件常用属性及方法
- 【android】android使用命令模拟按键
- 从android游戏框架看其生命周期!
- Android学习笔记3之基本组件API
- Android(安卓)使用Android(安卓)Studio + Gradle 或 命令行 进行