android学了快一年了,也写了一些代码,但是经常使用的application和context只是会简单的时候,有时候遇到问题也不知道为什么,最近上网查看了各种博客,对application和context有了一点了解,整理了一些资料,供大家探讨学习。
一、application
1、application是什么
Application是android系统的一个系统组件,当android程序启动的时候,系统会创建一个application对象。通常我们不需要自己去配置application,系统会自动帮我们创建一个默认的application,如果想自定义一个application,就需要继承application,并在manifest中的application中进行注册即可。
Android系统只会为每一个应用程序创建一个application,所以application是单例的,且在整个应用中生命周期最长,等于这个程序的生命周期。通常application可以用来传递数据(activity之间跳转),数据缓存等操作。
2、application如何自定义
(1)自定义MyApplication类,继承于Application
import android.app.Application;
import java.util.HashMap;
public class MyApplication extends Application{
private HashMap<String, Object> datas;
@Override
public void onCreate() {
super.onCreate();
datas = new HashMap<String, Object>();
}
public Object getData(String key){
return datas.get(key);
}
public void putData(String key, Object data){
datas.put(key, data);
}
}
说明:继承于Application类,主要重写里面的onCreate()方法,其实这次才是整个app程序的入口函数(部分人认为是activity的onCreat函数),在创建的时候,初始化变量的值,之后,整个app就可以存取数据了。该函数不能做需要大量时间才能完成的任务,不然会影响app的启动时间。
(2)MainActivity
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void toOtherActivity(View v){
MyApplication myApplication = (MyApplication)getApplication();
myApplication.putData("name", "paulzeng");
startActivity(new Intent(this, OtherActivity.class));
}
}
说明:该界面只有一个button,onClick属性为toOtherActivity
(3)OtherActivity
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class OtherActivity extends Activity{
private TextView nameTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_other);
nameTextView = (TextView)findViewById(R.id.name);
MyApplication myApplication = (MyApplication)getApplication();
String name = (String)myApplication.getData("name");
nameTextView.setText(name);
}
}
(4)配置MyApplication
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".OtherActivity">
</activity>
</application>
(5)搞起来
3、小结
这个案例演示使用application实现activity之间的数据共享,也可以用来实现数据传递,在MyApplication中再添加一个removeData的函数,在第二个界面获取数据之后,就可以把数据删除掉。当然还可以用自定义的application保存当前打开的activity,就可以实现在一个activity中,调用另一个activity的finish方法,关闭其它的界面。
二、context
1、context是什么
Context是一个系统抽象类,我们通过他访问应用程序的资源和启动各种组件(activity,service)以及获取系统服务。context被翻译成上下文,从名字可以看出它提供了一个运用可运行的环境,包括资源访问,组件和各服务的交互。Context定义了一套基本的功能接口,可以理解为一套规范,而activity和service是实现了这套规范的子类。
2、Context相关类的继承关系
说明:从这个继承关系图中可以看出,主要是ContextIml和ContextWrapper实现了Context接口,而ContextWrapper里面有一个ContextIml的实例,通过后面源代码的展示我们可以看出ContextWrapper只是提供了获取资源的方法,具体操作是调用ContextIml的方法。在我们常用的activity,service和application都属于Context的子类,这也就能说明为什么activity中调用一些函数时,要求传递Context,只需要传递this就搞定了。
(1)ContextWrapper部分源代码
public class ContextWrapper extends Context {
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
public Context getBaseContext() {
return mBase;
}
@Override
public AssetManager getAssets() {
return mBase.getAssets();
}
@Override
public Resources getResources()
{
return mBase.getResources();
}
@Override
public PackageManager getPackageManager() {
return mBase.getPackageManager();
}
@Override
public ContentResolver getContentResolver() {
return mBase.getContentResolver();
}
}
说明:从代码中可以看出,ContextWrapper只是覆写了Context的方法,每个方法里面调用实现了Context的ContextImpl的方法。
3、不同Context具有不同的能力
说明:NO1 表示Application context的确可以开始一个Activity,但是它需要创建一个新的task。这可能会满足一些特定的需求,但是在你的应用中会创建一个不标准的回退栈(back stack),这通常是不推荐的或者不是是好的实践。NO2 表示这是非法的,但是这个填充(inflation)的确可以完成,但是是使用所运行的系统默认的主题(theme),而不是你app定义的主题。NO3 在Android4.2以上,如果Receiver是null的话(这是用来获取一个sticky broadcast的当前 值的),这是允许的。
从这张图可以看出,虽然application,activity,Service都是Context的子类,但是他们都有一定的局限性,在使用的时候,并不是等价的,在使用的时候需要注意自己使用的场景。比如:我们在show a dialog,我们需要传递一个context,如果使用getApplicationContext()会造成crash,而使用activity就能解决这个问题,因为dialog属于activity,而application并没有承载界面。
参考文档:
http://www.cnblogs.com/renqingping/archive/2012/10/24/Application.html
http://www.360doc.com/content/13/0620/15/110467_294299969.shtml
http://blog.csdn.net/qinjuning/article/details/7310620
http://blog.csdn.net/race604/article/details/9331807