1. 程式人生 > >Android static靜態成員變數的使用誤區

Android static靜態成員變數的使用誤區

static 修飾的靜態變數,使用很方便,在不同的類和包中都可以使用,在虛擬機器中單獨佔用記憶體,沒錯,這些都是它們的優點,不過在專案上線後,才發現static有一些不太好的地方。
在檢視專案的崩潰資訊時,發現很多地方莫明的出現空指標異常的錯誤,經過排查,發現可能就是static的問題。我們在專案中,將使用者的資訊也就是User物件儲存成了一個靜態變數,而在報錯的地方,也都發現有使用過這種變數,因此,可以大致推斷出與這種儲存的方式有一定的聯絡。同時,有不少使用者反映在開啟應用的情況下,接個電話或者長時間待機後,再回到應用也會出現崩潰的現象,而這些崩潰都與靜態變數的空指標有關係。
如此來說的話,static靜態修飾在Android的開發中是不是很危險?或許我們可以說如果是static User u = new User();這樣定義的話,那麼應該不會有太大問題,而如果是static User u;這樣定義的話,那麼很可以會出現NULL的現象。當然,前面的方法裡面的屬性也可能會現空的情況,但是這個可以用封裝來避免空指標。另外靜態常量還是很好用的。
那麼應該如何儲存登入或者全域性的資訊呢?根據Google官方的推薦以及百度到的各位大神的推薦,我們應該儘量使用繼承自Application的自定義類,在我們繼承的類中定義需要全域性使用的變數,並通過getApplicationContext()來獲取和儲存相關的變數即可。例項:

package com.jony.bitmaptest;

import android.app.Application;
import android.os.Handler;

public class MyAplication extends Application{
    // 引發異常:在一些不規範的程式碼中經常看到Activity或者是Service當中定義許多靜態成員屬性。這樣做可能會造成許多莫名其妙的null pointer異常。
    
    // 異常分析:Java虛擬機器的垃圾回收機制會主動回收沒有被引用的物件或屬性。在記憶體不足時,虛擬機器會主動回收處於後臺的Activity或Service所
    // 佔用的記憶體。當應用再次去呼叫靜態屬性或物件的時候,就會造成null pointer異常
    
    // 解決異常:Application在整個應用中,只要程序存在,Application的靜態成員變數就不會被回收,不會造成null pointer異常
    private static final int MSG = 0X1;
    private Handler mHandler = new Handler(){
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                case MSG:
                    
                    break;

                default:
                    break;
            }
        };
    };
    private String action;
    private String username;
    private String password;
    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getAction() {
        return action;
    }
    public void setAction(String action) {
        this.action = action;
    }
    public Handler getHandler(){
        return mHandler;
    }
}

在Activity或Service中的使用方法:

MyApplication application = (MyApplication) this.getApplicationContext(); 

Application是與應用同時存在的,也就是應用在它就在,並不會被GC給莫名其妙的回收掉,因此,使用此方法更加安全。

連結地址