2016-05-18 10 views
0

私は静的なクラスを使うことの落とし穴についてたくさん読んできました。静的クラスのスタイル、フォント、イメージを参照していますか?

しかし、すべてのスタイル、画像、フォントなどを保持する静的なクラスを作成する際に、私にとって大きなメリットがあります。これはパフォーマンスやデザインの悪さに悪いことでしょうか?私はいくつかのコードを持って何を意味するか、これは静的クラスからのもので説明するために

button2Style = new TextButtonStyle(); 
    button2Style.up = new NinePatchDrawable(buttonAtlas.createPatch("button2")); 
    button2Style.down = new NinePatchDrawable(buttonAtlas.createPatch("button2")).tint(Color.GRAY); 
    button2Style.font = font_rr_65; 
    button2Style.fontColor = Colors.PURPLE; 

その後、私は別のクラスでは、このようにそれを参照したい:

TextButton txtB = new TextButton("Hello", StaticClass.button2Style); 
+0

これは、静的クラスを誤って使用することに比べて、静的クラスを使用することの一般的な落とし方が少なくなります。一貫したアプリケーション全体のスタイルでは、これは適切なようです。 – Compass

答えて

3

通常、静的な使用は、通常、オブジェクト指向の設計が悪いことを示していますが、それ以上に注意してください。 スタティックのライフサイクルは、ライフサイクルと同じようにリソースはに作成されます。

はのは、一例として@BasimKhajwalの答えを見てみましょう:

class Assets { /*...*/ 
    private static final AssetManager assetManager = new AssetManager(); 

このコードnew AssetManager()が実際に実行されますか?これは、VMが初期化された後に実際に直接実行されます。したがって、アプリケーションウィンドウが実際に作成される前であっても、すべてのネイティブライブラリがロードされてOpenGLコンテキストが作成される前であってもかまいません。

public static void loadAll() { /* load things */ } 

このコードはいつ実行されますか?これはおそらく、あなたのApplicationListenerのcreateメソッドのどこかで呼び出します。したがって、のOpenGLコンテキストでは、アプリケーションの特定のインスタンスが作成され、その時点でアクティブになり、そのアプリケーションのレンダースレッドで呼び出されます。

は今のAndroid上で動作して、次のような状況を考慮してください。

あなたのVM静的な資産は、そのアプリケーションのコンテキストにロードされ、あなたはそのコンテキストでそれらを使用することができます。その後、電話がかかり、アプリケーションがバックグラウンドでプッシュされます。しばらくすると、Androidはメモリを解放する必要があると判断し、OpenGLのコンテキストなどを含むアプリケーションを閉じます。

電話が終了したら、ゲームに戻ります。 Androidはあなたのゲームの新しいインスタンスを開始します。そのため、同じAssetManagerと既にロードしているすべてのアセットを含む、アプリケーションの前のインスタンスの同じVMを再利用します。アプリケーションは新しいOpenGLコンテキストなどを作成しますが、アセットは以前の無効なコンテキストを指しています。したがって、資産を無効にし、望ましくない行動を引き起こします。

もちろん、通常のテストではこのような問題は見つけられません。 Androidがアプリケーションを閉じてVMをリサイクルするかどうかは保証されません。しかし、いくつか試してみると、上記のステップを再現できるはずですので、リソースがどのように無効になっているかを自分で確認できます(たとえば、テクスチャが黒くなるなど)。 saidの場合でも、アプリケーションの複数のインスタンスを同じVMで実行することができます(Playストアと起動画面から起動する場合など)。

この問題を回避することができます。例えば、libGDXはアプリケーションの各インスタンスに対してすべてのリソースのMapを保持することで内部的にそれを行います(どのように動作しているかは、hereの例です)。しかし、最初にObject Oriented Designを適切に実装していない可能性が高いので、あなたのアプローチを再考する方がよいでしょう。

staticをまだ使用する場合は、ライフサイクルを完全に理解してください(アプリケーションの特定のインスタンスよりも寿命が長い、またはそれに限定されているとは限りません)。

これは恐らく最も大きな間違いの1つであることに注意してください(「仮想」ピクセルの隣に)。ちょっと検索すると、特にAndroidで静的な問題がある人の例がかなり見つかります。ただし、Androidで最も多く出展していますが、デザイン上の問題です。 Androidをターゲットにしていないときにあなたに当てはまるわけではありません。静的リソース(または重要な静的変数)がまったく必要ないように、アプリケーションを設計することは完全に可能です。

+0

良い情報ありがとう! –

+0

訂正ありがとう!これからも私はこれを学び、これを私の将来のプロジェクトに取り入れます。 –

+0

私はAssetManagerがアプリケーションの 'destroy'メソッド(私のプロジェクトと同じように)でクリアされてもエラーは発生しないと考えていますか? (Android/Desktop/HTML5では今までに何も起こっていませんでした) –

1

編集私は間違っていると分かります。(Xoppaの答えを参照してください。)

個人的には、libGDXとゲーム開発に特に役立つ静的クラスを使用しています。

thisのような記事を読むと、人々は静的な変数の使い方に嫌われがちです。通常、変更がデバッグや理由付けをするのが難しくなる可能性があるグローバルな状態を持つため、強調は可変です。変数が静的であると、コードのどの部分がこれらの変更を引き起こしている可能性があり、プログラムのまったく異なる部分でバグやクラッシュが発生する可能性があります。

あなたの資産は、ゲームの生涯のほとんどにわたって一定です。つまり、デバッグに干渉しないことを意味します。また、大部分のゲームは起動時にすべてのアセットを読み込むため、アセットをゲームの全期間にわたってロードする必要があります。それらを静的に保つことはメモリ使用量にほとんど違いを生じさせません。

私のゲームでは、Assetsという静的なクラスがあり、組み込みのAssetManagerクラスを使用する傾向があります。次に、定数として格納されているファイルパスを使用して、すべてのアセットを簡単に参照できます。こうすることで、他のクラスが静的テクスチャを編集できなくなり、テクスチャを簡単に反復処理できます。

例:

class Assets { 

    /* Use built-in libGDX asset manager to load/store all assets */ 
    private static final AssetManager assetManager = new AssetManager(); 

    /* Use private constructor to prevent instantiation */ 
    private Assets() { } 

    /* 
     Public constants to be referenced by other classes 
    */ 
    public static final String BAD_GUY = "images/bad_guy.png"; 
    public static final String GOOD_GUY = "images/good_guy.png"; 

    /* 
     Private arrays of all textures/sounds/fonts for loading 
    */ 
    private static final String[] TEXTURES = { 
     BAD_GUY, 
     GOOD_GUY; 
    }; 

    /* Load method for all assets called by your main game handler at start */ 
    public static void loadAll() { 

     //Setup the load queue for all textures 
     for (String texture: TEXTURES) 
      assetManager.load(texture, Texture.class); 

     //Load everything 
     assetManager.finishLoading(); 

     /* Do all the post processing here */ 
    } 

    /* Access method for textures the parameter name is from above e.g. Assets.BAD_GUY */ 
    public Texture getTexture(String name) { 
     return assetManager.get(name, Texture.class); 
    } 
} 

あなたは実際の例を見たい場合は、自分のゲームファイルを見ることができます: https://github.com/basimkhajwal/LSD/blob/master/core/src/net/net63/codearcade/LSD/managers/Assets.java

用心、それはそれは音が含まれていると少し複雑です、アニメーションやいくつかのゲーム固有のコードがありますが、主な原則は同じです。

関連する問題