Android Application理解

来源:互联网 发布:vc编程软件 编辑:程序博客网 时间:2024/05/22 13:05

转载请注明出处:http://blog.csdn.net/mr_liabill/article/details/48347577   来自《LiaBin的博客》

Application概念

/**
 * Base class for those who need to maintain global application state. You can
 * provide your own implementation by specifying its name in your
 * AndroidManifest.xml's <application> tag, which will cause that class
 * to be instantiated for you when the process for your application/package is
 * created.
 *
 * <p class="note">There is normally no need to subclass Application.  In
 * most situation, static singletons can provide the same functionality in a
 * more modular way.  If your singleton needs a global context (for example
 * to register broadcast receivers), the function to retrieve it can be
 * given a {@link android.content.Context} which internally uses
 * {@link android.content.Context#getApplicationContext() Context.getApplicationContext()}
 * when first constructing the singleton.</p>
 */
Application类是为了那些需要保存全局变量设计的基本类,你可以在AndroidManifest.xml的<application>标签中进行自己的实现,这样的结果是:当你的application或者包被建立的时候将引起那个类被建立。通常情况下是没必要继承Application,多数情况下,静态单例可以以更模块的方式提供相同的功能,假如你的单例需要一个全局context(比如注册一个广播接收器)……

往简单点说,如果自定义一个单例,如果需要获取系统字符串资源,还需要传进来一个context才能获取,比如context.getString(),但是如果在Application里面就不需要了,直接使用getString()

android系统会为每个程序运行时创建一个Application类的对象且仅创建一个,所以Application可以说是单例 (singleton)模式的一个类,且application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。因为它是全局且application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。因为它是全局的单例的,所以在不同的Activity,Service中获得的对象都是同一个对象。所以通过Application来进行一些,数据传递,数据共享等,数据缓存等操作。

    /**
     * Called when the application is starting, before any activity, service,
     * or receiver objects (excluding content providers) have been created.
     * Implementations should be as quick as possible (for example using
     * lazy initialization of state) since the time spent in this function
     * directly impacts the performance of starting the first activity,
     * service, or receiver in a process.
     * If you override this method, be sure to call super.onCreate().
     */
    @CallSuper
    public void onCreate() {
    }

Application的onCreate才是程序的入口,第一个被调用,所以如果有需要最开始就初始化的全局变量可以放在这里,但是这个方法必须尽量少的做一些事情,否则的话就会影响到第一个启动的activity,service,receiver,会有延迟嘛,影响用户体验


使用

<application android:name="××××">

MyApplication application=(MyApplication) getApplication();
MyApplication application=(MyApplication) getApplicationContext();


关于getApplication()和getApplicationContext()有何区别,可以参考:

http://stackoverflow.com/questions/5018545/getapplication-vs-getapplicationcontext

--------------------------------------------------------------------------------------------------------------------

Although in current Android Activity and Service implementations, getApplication() andgetApplicationContext() return the same object, there is no guarantee that this will always be the case (for example, in a specific vendor implementation).

So if you want the Application class you registered in the Manifest, you shouldnever call getApplicationContext() and cast it to your application, because it may not be the application instance (which you obviously experienced with the test framework).

Why does getApplicationContext() exists in the first place ?

getApplication() is only available on the Activity class and in the Service class, whereasgetApplicationContext() is declared in the Context class.

That actually means one thing : when writing code in a broadcast receiver, which is not a context but is given a context in its onReceive method, you can only callgetApplicationContext(). Which also means that you are not guaranteed to have access to your application in a BroadcastReceiver.

When looking at the Android code, you see that when attached, an activity receives a base context and an application, and those are different parameters.getApplicationContext() delegates it's call to baseContext.getApplicationContext().

One more thing : the documentation says that it most cases, you shouldn't need to subclass Application:

There is normally no need to subclass Application. In most situation, static singletons can provide the same functionality in a more modular way. If your singleton needs a global context (for example to register broadcast receivers), the function to retrieve it can be given a Context which internally uses Context.getApplicationContext() when first constructing the singleton.

I know this is not an exact and precise answer, but still, does that answer your question?

--------------------------------------------------------------------------------------------------------------------

举例说明

public class MyApplication extends Application {    private int count = 1;    @Override    public void onCreate() {        super.onCreate();    }    public int getCount() {        return count;    }    public void setCount(int count) {        this.count = count;    }    public String getAppName() {        return getString(R.string.app_name);    }}MainActivity    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ((MyApplication) getApplication()).setCount(100);        startBut = (Button) findViewById(R.id.start);        startBut.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent = new Intent(MainActivity.this, AnoActivity.class);                startActivity(intent);            }        });    }AnoActivity@Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_ano);        textView = (TextView) findViewById(R.id.text);        String count = String.valueOf(((MyApplication) getApplication()).getCount());        //String count= String.valueOf(new MyApplication().getCount());        textView.setText(count);    }
此时textView的值为100,如果替换为这行String count= String.valueOf(new MyApplication().getCount());此时textView就为1了

这里不需要自己实现getInstance,变量也不要设置为static,所有通过getApplication() getApplicationContext() 获取得到的都是同一个单例Application对象,系统自动创建的
但是不要很傻很天真的去这样调用String count= String.valueOf(new MyApplication().getCount());这样操作的就不是系统自动创建的Application对象了

通过Application传递数据

假如有一个Activity A, 跳转到 Activity B ,并需要推荐一些数据,通常的作法是Intent.putExtra() 让Intent携带,或者有一个Bundle把信息加入Bundle让Intent推荐Bundle对象,
实现传递。但这样作有一个问题在于,Intent和Bundle所能携带的数据类型都是一些基本的数据类型,如果想实现复杂的数据传递就比较麻烦了,通常需要实现 Serializable
或者Parcellable接口。这其实是Android的一种IPC数据传递的方法。如果我们的两个Activity在同一个 进程当中为什么还要这么麻烦呢,只要把需要传递的对象的引用传递过去就可以了。基本思路是这样的。在Application中创建一个HashMap ,以字符串为索引,Object为value这样我们的HashMap就可以存储任何类型的对象了。在Activity A中把需要传递的对象放入这个HashMap,然后通过Intent或者其它途经再把这索引的字符串传递给Activity B ,Activity B 就可以根据这个字符串在HashMap中取出这个对象了。只要再向下转个型 ,就实现了对象的传递。


其它

Button button = new Button(this);
Button button = new Button(getApplicationContext());
刚开始学的那会,我还傻很天真的认为,因为button持有ApplicationContext,然后可能会造成内存泄漏呢。
其实不然,因为是否回收释放对象,取决于对象是否有其它引用正在指向它。所以这个对象持有一个全局对象或者static对象就不能被回收就大错特错

实际内存泄漏情况如下,
activity.finish()  
new SingleInstance(context);//这里是单例
系统准备回收activity资源,但是发现这个activity对象还被引用着,new SingleInstance(context);所以不能被回收,内存泄漏
0 0