【问题标题】:Which is called first the constructor or onDraw() [duplicate]首先调用构造函数或 onDraw() [重复]
【发布时间】:2014-08-04 00:24:38
【问题描述】:

我提到了this question,但它没有提供我要问的内容。

我有一些全局声明的变量,最初它们被分配为 NULL。在构造函数中,我调用了一个名为"newGame()" 的函数,该函数初始化变量。在onDraw() 内部,我试图绘制一个文本,其中包含我在newGame() 函数中初始化的变量之一的大小,当我运行应用程序时,它崩溃了,logCat 说:NPE .

所以,我认为,如果首先调用构造函数,我的变量应该已经被初始化,所以不应该有NPE。但是,既然有NPE,看来onDraw()是在构造函数之前调用的,是这样吗?

Update_1

我还将newGame() 函数放在onSizeChanged() 中,但是我收到了相同的NPE

Update_2

我正在检查 hashmap 的对象是否为空,如下所示: if (obj == null)判断一个对象是否为空是否正确?

Update_3

这是我如何初始化“手”

if (hand == null) {
        Log.i(TAG, "@dealCards: Hand hashMap was NULL, it will be initialised");
        hand = new HashMap<Integer, Card>();
    }

代码

private HashMap<Integer, Card> deck = null;
private HashMap<Integer, Card> tableHand = null;
private HashMap<Integer, Card> myHand = null;
private HashMap<Integer, Card> compHand = null;
....
....
//CONSTRUCTOR
    public GameView(Context context) {
    super(context);
    // TODO Auto-generated constructor stub
    mContext = context;
    scale = mContext.getResources().getDisplayMetrics().density;

    textPaint = new Paint();
    textBounds = new Rect();
    deckSize_String = "Deck_Size: ";
    cardArraySize_String = "cardsArraySize: ";

    textPaint.setAntiAlias(true);
    textPaint.setColor(Color.RED);
    textPaint.setStyle(Paint.Style.STROKE);
    textPaint.setTextAlign(Paint.Align.LEFT);
    textPaint.setTextSize(scale*15);

    newGame();
}
....
....
//OnDraw()
    protected void onDraw(Canvas canvas) {
    // TODO Auto-generated method stub
    super.onDraw(canvas);
    canvas.drawText("tableHand: "+tableHand.size(), 10, 200, textPaint);

}

private void newGame() {
    // TODO Auto-generated method stub
    Log.i(TAG, "@newGame()");

    initDeck();
    dealCards(deck, tableHand);
    myTurn = whosTurn();

    if (myTurn) {
        dealCards(deck, myHand);
        dealCards(deck, compHand);
    }else {
        dealCards(deck, myHand);
        dealCards(deck, compHand);
    }
}
...
...
...
 private void dealCards(HashMap<Integer, Card> deck, HashMap<Integer, Card> hand) {
    // TODO Auto-generated method stub
    if (hand == null) {
        Log.i(TAG, "@dealCards: Hand hashMap was NULL, it will be initialised");
        hand = new HashMap<Integer, Card>();
    }

    for (int i=0; i<4; i++) {
        hand.put( (hand.size()+1), deck.get( ((DECK_MAX_SIZE - deck.size())+1) ) );
        copyDealtCards( dealtCardsPile, deck.get( ((DECK_MAX_SIZE - deck.size())+1) ) );
        deck.remove( ((DECK_MAX_SIZE - deck.size())+1) );
    }
}

【问题讨论】:

  • 如果构造函数没有被调用,onDraw()会被调用到什么地方?
  • 把代码贴出来让大家看看
  • 在对象上调用任何非静态函数之前,必须先调用构造函数。
  • @SotiriosDelimanolis 如果没有构造函数,但是,onDraw() 将尝试绘制尚未初始化的文本。是你的问题吗,我说对了吗?
  • @kharyam 我发布了代码

标签: java android ondraw


【解决方案1】:

更新

看到您添加的代码,您在哪里初始化 tableHand?

顺便说一句,tableHand 最好声明为 Map 而不是 HashMap,并用 new HashMap() 进行初始化。


毫无疑问,构造函数。如果对象首先不存在,则不能对其调用任何实例方法。

【讨论】:

  • 对于非静态方法
  • 您可以在不创建类实例的情况下调用静态方法。
【解决方案2】:

为什么不尝试遵循此设计以确保正确启动变量

class Foo {
    private static String GLOBAL_VAR = null ;
    private        String instanceVariable = null ;

    static {
        // here you can do complicated stuff 
        //in order to correctly initiate your variables.
        GLOBAL_VAR = "FOO" ; 
    }// this block will run when the class is loaded

    {
        // here you can do complicated stuff 
        //in order to correctly initiate your variables.
        instanceVariable = "foo" ;  
    }// this block will run before constructor.

    Foo()
    {

    }//Constructor

    static String getGlobalVar()
    {
         return GLOBAL_VAL ;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-21
    • 2012-05-19
    • 2010-09-13
    • 1970-01-01
    • 2018-12-02
    • 2018-10-17
    • 1970-01-01
    相关资源
    最近更新 更多