Android中Context详解
16lz
2022-01-11
原文地址:Android中的Context详解 作者:phoenixcsl
转自: http://blog.csdn.net/qq272803220/article/details/7327178Android基础概念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);
- }
点击(此处)折叠或打开
- public class myactivity extends Activity {
- private static Drawable sBackground;
- protected voidonCreate(Bundle state) {
- super.onCreate(state);
- TextView label = new TextView(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 = new Intent();
- intent.setClass(A.this, B.class);
- Bundle bundle =new Bundle();
- bundle.putString("Info", "Information");
- intent.putExtras(bundle);
- startActivity(intent);
- Intent intent = new Intent();
- intent.setClass(A.this, B.class);
- Bundle bundle = new Bundle();
- bundle.putString("Info", "Information");
- intent.putExtras(bundle);
- startActivity(intent);
点击(此处)折叠或打开
- class MyApp extends Application {
- private String myState;
- public String getState() {
- return myState;
- }
- public void setState(String s) {
- myState = s;
- }
- }
点击(此处)折叠或打开
- android:name=".MyApp"
- android:icon="@drawable/icon"
- android:label="@string/app_name">
点击(此处)折叠或打开
- class Blah extends Activity {
- @Override
- public void onCreate(Bundle b){
- ...
- MyApp appState = ((MyApp)getApplicationContext());
- String state = appState.getState(); ...
- }
- }
[小技巧]在任意位置获取应用程序Context - [Android学习笔记]
Android程序中访问资源时需要提供Context,一般来说只有在各种component中(Activity, Provider等等)才能方便的使用api来获取Context, 而在某些工具类中要获取就很麻烦了。为此,我们可以自定义一个Application类来实现这种功能。
点击(此处)折叠或打开
- import android.app.Application;
- public class MyApplication extends Application {
- private static MyApplication instance;
- public static MyApplication getInstance() { return instance; }
- @Override
- public void onCreate() {
- // 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,代码如下:
点击(此处)折叠或打开
- package chroya.demo;
- import android.app.Activity;
- import android.os.Bundle;
- import android.util.Log;
- class Main extends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
- public voidprint(String msg) {
- Log.d("Main", "msg:"+ msg);
- }
- }
点击(此处)折叠或打开
- Context c = createPackageContext("chroya.demo",
- Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
- //载入这个类
- Class clazz = c.getClassLoader().loadClass("chroya.demo.Main");
- //新建一个实例
- Object owner =clazz.newInstance();
- //获取print方法,传入参数并执行
- Object obj = clazz.getMethod("print", String.class).invoke(owner, "Hello");
更多相关文章
- android 6.0後讀取外部SD卡的路徑的方法
- Android的线程使用来更新UI----Thread、Handler、Looper、TimerT
- android UI进阶之弹窗的使用(2)--实现通讯录的弹窗效果
- Android(安卓)UI学习 - Tab的学习和使用
- 浅谈Java中Collections.sort对List排序的两种方法
- 箭头函数的基础使用
- NPM 和webpack 的基础使用
- Python list sort方法的具体使用
- 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程