/frameworks/base/core/java/android/content/Intent.java./frameworks/base/core/java/android/content/Context.java./frameworks/base/core/java/android/app/ContextImpl.java./frameworks/base/core/java/android/app/Activity.java./frameworks/base/core/java/android/app/ActivityThread.java./frameworks/base/core/java/android/view/ContextThemeWrapper.java./frameworks/base/core/java/android/content/ContextWrapper.java--------------------------------------------------------------------------------Activity与ContextImpl的关联:继承关系:public class Activity extends ContextThemeWrapperpublic class ContextThemeWrapper extends ContextWrapperpublic class ContextWrapper extends Contextclass ContextImpl extends ContextActivity本身是一个Context类型的子类。在ContextWrapper中间接实现了Context相关的方法,所以Activity也具有这些方法。而在ContextWrapper中对Context相关的方法的实现实际上是调用mBase的相关方法的。而这个mBase实际上就是ContextImpl的实例。也就是说,所有Context子类型的对象调用Context相关方法时,实际上都是调用的ContextImpl实例的方法。mBase的赋值是在ContextWrapper的以下方法中: protected void attachBaseContext(Context base) { if (mBase != null) { throw new IllegalStateException("Base context already set"); } mBase = base; }而这个方法的调用是在Activity的以下方法中: final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, Object lastNonConfigurationInstance, HashMap<String,Object> lastNonConfigurationChildInstances, Configuration config) { attachBaseContext(context);而这个方法的调用是在ActivityThread的以下方法中: private final Activity performLaunchActivity(ActivityRecord r, Intent customIntent) activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); Application app = r.packageInfo.makeApplication(false, mInstrumentation); ContextImpl appContext = new ContextImpl(); appContext.init(r.packageInfo, r.token, this); activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstance, r.lastNonConfigurationChildInstances, config); mInstrumentation.callActivityOnCreate(activity, r.state);这个方法是在luncher一个Activity时调用的。通过方法可以看出,系统首先创建一个Activity对象,然后构造相关的Application对象。之后,创建ContextImpl对象,并调用init方法初始化相关成员,之后将其添加给Activity对象。这样,Activity就和ContextImpl对象关联上了。在之后会调用Activity相关的回调函数,比如onCreate()等。--------------------------------------------------------------------------------Android关于Intent对象创建时报异常相关调查<示例代码>public class MyServiceActivity extends Activity { private Button startSer1; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); startSer1 = (Button) findViewById(R.id.startSer1); startSer1.setOnClickListener(btnListener); } private OnClickListener btnListener = new OnClickListener() { private Intent intent = new Intent(MyServiceActivity.this, MyService.class); @Override public void onClick(View v) { } };}<问题>程序在加载时会报异常,位置是 private Intent intent = new Intent()。而将该Intent对象的创建放到onClick中就没有问题。<分析>1、需要理解Intent对象的创建过程: public Intent(Context packageContext, Class<?> cls) { mComponent = new ComponentName(packageContext, cls); } public ComponentName(Context pkg, Class<?> cls) { mPackage = pkg.getPackageName(); mClass = cls.getName(); }可以看到,最后会调用pkg对象的getPackageName方法。而getPackageName方法的实现是在ContextImpl中: public String getPackageName() { if (mPackageInfo != null) { return mPackageInfo.getPackageName(); } throw new RuntimeException("Not supported in system context"); }这里又调用了mPackageInfo成员的getPackageName方法。而mPackageInfo成员是在ContextImpl的init方法中赋值的: final void init(ActivityThread.PackageInfo packageInfo, IBinder activityToken, ActivityThread mainThread, Resources container) { mPackageInfo = packageInfo;而这个方法是在创建完Activity的实例之后,创建Application信息时调用的: private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); Application app = r.packageInfo.makeApplication(false, mInstrumentation); ContextImpl appContext = new ContextImpl(); appContext.init(r.packageInfo, r.token, this); activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstance, r.lastNonConfigurationChildInstances, config); mInstrumentation.callActivityOnCreate(activity, r.state);也就是说,如果要创建一个Intent对象,必须在ContextImpl对象的init方法运行完之后才可以。而Activity对象的创建明显处在ContextImpl对象的init方法调用之前。而Activity的onCreate方法的调用则处在ContextImpl对象的init方法调用之后: public void callActivityOnCreate(Activity activity, Bundle icicle) { activity.onCreate(icicle);2、出错原因主要是,Intent对象的创建是在Listener对象创建时创建的,而它的创建又依赖于Activity对象: private Intent intent = new Intent(MyServiceActivity.this, MyService.class);(该方法中的第一个参数是一个Context的实例)Listener对象是在Activity创建时创建的,: private OnClickListener btnListener = new OnClickListener() {而此时,Activity对象还没有创建完成,ContextImpl的init方法还没有被调用。所以,此时创建Intent对象时,会因为没有mPackageInfo成员而创建失败。所以,整个程序在启动的过程中,当创建到Activity对象的Listener对象的Intent对象时就直接报空指针异常了。3、正确的做法是:1、要么将Listener对象的创建放到onCreate中。2、要么将Intent的创建放到onCreate中或者onClick中。当然,还存在其它修改方法,但都大同小异。而本质都是在创建Intent对象时,保证Activity的相关环境已经初始化完成。通过以上分析可以看出,严格遵循Activity的生命周期进行编程才能写出健壮不易出错的代码。
转载自http://hi.baidu.com/gaogaf/blog/item/7efdb01185806264ca80c4d9.html
分享到:
相关推荐
android activityIntent 传值 传对象
android Intent传递对象数据 通过对象分别实现Serializable Parcelable接口的两种方法
Xamarin.Android之Intent传递对象简单实例,实现的是IParcelable接口
Android 通过Intent使用Bundle传递对象 Android开发中有时需要在应用中或进程间传递对象,下面详细介绍Intent使用Bundle传递对象的方法。 被传递的对象需要先实现序列化,而序列化对象有两种方式:java.io....
Intent可以携带一些数据,比如基本类型数据int、Boolean,或是String,或是序列化对象,Parcelable与Serializable。 Intent传递数据时,如果数据太大,可能会出现异常。比如App闪退,或是Intent发送不成功,logcat...
Android Intent传递对象小结
主要为大家详细介绍了Android利用Intent启动和关闭Activity的相关操作,感兴趣的小伙伴们可以参考一下
android中Intent传递对象的两种方法(Serializable,Parcelable) 简单而又详细的demo,欢迎下载
通过一个实验,讲解Android的使用方法,总结详细
Android+Intent机制实例详解 Android+Intent 大家不得不看啊!
android Intent例子源码android Intent例子源码android Intent例子源码android Intent例子源码android Intent例子源码android Intent例子源码
Intent传递对象、对象数组
android 利用intent调用activity 简明精炼的例子 传递数据,并且有返回值
Android使用Intent实现Video功能
Intents and Intent Filters 三种应用程序基本组件——activity, ... 在上述三种情况下, android系统会自己找到合适的activity, service, 或者 broadcast receivers来响应intent. 三者的intent相互独立互不干扰.
我们可以通过Intent类中的putExtra方法可以将简单的数据类型和序列化对象保存到Intent对象中,然后在目标的Activity中使用getXxx方法取出对应的数据。
Android使用Intent实现Camera功能
个人整理的Android Intent的使用介绍 Android 组件之间的信使Intent Android 中的数据存取和ContentProvider
Android+Intent机制实例详解.rar,详细的介绍了,android中的intent知识,可以下载下来看看哟