1

Android ゲームを開発していて、メイン メニューを追加しました。これは別のアクティビティであるため、誰かがメニューの「新しいゲーム」ボタンをクリックすると、ゲーム アクティビティへの新しいインテントが開かれます。

私の問題は、ユーザーが「戻る」を押すと、ゲームが閉じてメインメニューに戻ることです。「New Game」をもう一度押すと、クラッシュします。

ゲームの 2 番目のバージョンを作成しようとしていて、メモリが不足していると思います。メニューにゲーム アクティビティのコピーを保持しておき、もう一度 [新しいゲーム] をクリックした場合に再度開く必要がありますか? または、これを行う簡単な方法はありますか?

私の「新しいゲーム」ボタン リスナーは次のことを行います: (IslandGame は私のメイン ゲーム クラスです。バンドルは、新しいゲームを開始するか、以前のゲームをロードするか、どのレベルで開始するかを伝えるためのものです)

ButtonNewGame.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {                 
            Bundle bundle = new Bundle();
            bundle.putString("RESTORE", "NEW"); //in the restore key, say we want a new game
            bundle.putInt("CAMPAIGN", 1); //start in campaign #1

            Intent intent = new Intent(Intent.ACTION_RUN);
            intent.putExtras(bundle);
            intent.setClassName(thisActivity, IslandGame.class.getName());
            startActivity(intent);
        }         
    });

ログキャットは次のとおりです。

06-09 17:42:34.199: E/dalvikvm-heap(239): 147456-byte external allocation too large for this process.
06-09 17:42:34.199: E/(239): VM won't let us allocate 147456 bytes
06-09 17:42:34.209: D/AndroidRuntime(239): Shutting down VM
06-09 17:42:34.209: W/dalvikvm(239): threadid=3: thread exiting with uncaught exception (group=0x4001b188)
06-09 17:42:34.219: E/AndroidRuntime(239): Uncaught handler: thread main exiting due to uncaught exception
06-09 17:42:34.249: E/AndroidRuntime(239): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.dylan.island/com.dylan.island.IslandGame}: android.view.InflateException: Binary XML file line #37: Error inflating class <unknown>
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2496)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.app.ActivityThread.access$2200(ActivityThread.java:119)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.os.Handler.dispatchMessage(Handler.java:99)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.os.Looper.loop(Looper.java:123)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.app.ActivityThread.main(ActivityThread.java:4363)
06-09 17:42:34.249: E/AndroidRuntime(239):  at java.lang.reflect.Method.invokeNative(Native Method)
06-09 17:42:34.249: E/AndroidRuntime(239):  at java.lang.reflect.Method.invoke(Method.java:521)
06-09 17:42:34.249: E/AndroidRuntime(239):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
06-09 17:42:34.249: E/AndroidRuntime(239):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
06-09 17:42:34.249: E/AndroidRuntime(239):  at dalvik.system.NativeStart.main(Native Method)
06-09 17:42:34.249: E/AndroidRuntime(239): Caused by: android.view.InflateException: Binary XML file line #37: Error inflating class <unknown>
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.view.LayoutInflater.createView(LayoutInflater.java:513)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:565)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.view.LayoutInflater.rInflate(LayoutInflater.java:618)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.view.LayoutInflater.rInflate(LayoutInflater.java:621)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.view.LayoutInflater.rInflate(LayoutInflater.java:621)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.view.LayoutInflater.inflate(LayoutInflater.java:407)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
06-09 17:42:34.249: E/AndroidRuntime(239):  at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:198)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.app.Activity.setContentView(Activity.java:1622)
06-09 17:42:34.249: E/AndroidRuntime(239):  at com.dylan.island.IslandGame.onCreate(IslandGame.java:76)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
06-09 17:42:34.249: E/AndroidRuntime(239):  ... 11 more
06-09 17:42:34.249: E/AndroidRuntime(239): Caused by: java.lang.reflect.InvocationTargetException
06-09 17:42:34.249: E/AndroidRuntime(239):  at com.dylan.island.IslandView.<init>(IslandView.java:1983)
06-09 17:42:34.249: E/AndroidRuntime(239):  at java.lang.reflect.Constructor.constructNative(Native Method)
06-09 17:42:34.249: E/AndroidRuntime(239):  at java.lang.reflect.Constructor.newInstance(Constructor.java:446)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.view.LayoutInflater.createView(LayoutInflater.java:500)
06-09 17:42:34.249: E/AndroidRuntime(239):  ... 23 more
06-09 17:42:34.249: E/AndroidRuntime(239): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.graphics.Bitmap.nativeCreate(Native Method)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.graphics.Bitmap.createBitmap(Bitmap.java:468)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.graphics.Bitmap.createBitmap(Bitmap.java:435)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:340)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:488)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:462)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:323)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:346)
06-09 17:42:34.249: E/AndroidRuntime(239):  at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:372)
06-09 17:42:34.249: E/AndroidRuntime(239):  at com.dylan.island.IslandView$IslandThread.initimages(IslandView.java:435)
06-09 17:42:34.249: E/AndroidRuntime(239):  at com.dylan.island.IslandView$IslandThread.beginLevel(IslandView.java:220)
06-09 17:42:34.249: E/AndroidRuntime(239):  at com.dylan.island.IslandView$IslandThread.<init>(IslandView.java:215)
06-09 17:42:34.249: E/AndroidRuntime(239):  ... 27 more
4

5 に答える 5

1

避けるためにjava.lang.OutOfMemoryError: bitmap size exceeds VM budget

ゲームのメイン アクティビティを破棄してメニュー アクティビティに移動するときに、ゲームで使用されるすべての画像をリサイクルする必要があると思います。

大量の画像を使用する場合の適切な方法については、次のリンクを参照してください。

http://android-developers.blogspot.co.uk/2009/01/avoiding-memory-leaks.html

画像を Bitmap オブジェクトにロードする際の奇妙なメモリ不足の問題

OutofMemoryError: ビットマップ サイズが VM の予算を超えています (Android)

于 2012-06-09T08:33:55.847 に答える
0

ゲームの 2 番目のバージョンを作成しようとしていて、メモリが不足していると思います。

あなたは絶対に正しいです。ゲーム アクティビティを適切に終了した場合は、最初のバージョンがなくなっているため、2 番目のバージョンを作成しようとしているはずです。

メニューにゲーム アクティビティのコピーを保持しておき、もう一度 [新しいゲーム] をクリックした場合に再度開く必要がありますか?

一般に、これは多くの理由から非常に悪い習慣と見なされています。これらの中で最も重要なのは、コンテキストによるメモリ リークです。

または、これを行う簡単な方法はありますか?

ゲーム アクティビティを singleTask または singleInstance として定義できます。これに関する (現時点での) 問題は、メモリのバグを修正するソリューションではないことです。SingleTasks は、複数インスタンス アプリケーションとは異なる方法でプログラミングされており、他にも考慮事項があります。あなたの問題は、そもそもメモリが使用されているという事実にあるため、このルートに進む前に、次のことを必ず確認します。

  1. すべてのリソースが解放されていることを確認してください。ここで特に懸念されるのは、ビューへの静的参照です。それらがある場合は、それらをクリーンアップします。

  2. すべてのビットマップがリサイクルされていることを確認してください。ビットマップのサイズを変更すると、オリジナルが取り残されることがあります。多くの場合、ばかげた見落としです。ちょっと見てください。:)

  3. ファイルにアクセスしている場合は、ファイルが閉じていることを確認してください。ほとんど問題はありませんが、常に試してみる価値があります。

  4. ゲーム アクティビティの終了後に System.gc() 呼び出しを追加します。これは、リソースのメジャー リリース後に非常に役立ちます。残念ながら、それは保証されていません。あなたの場合、メインメニューの onResume() で最適かもしれません。

これらすべてを使い果たしたら、singleTask ルートを実装するだけです。

お役に立てれば、

ファジカルロジック

于 2012-06-09T08:51:42.610 に答える
0

試す

Intent intent = new Intent(YourCurrentActivity.this, IslandGame.class);
intent.putExtra("Restore", "NEW");
intent.putExtra("CAMPAIGN", 1);
startActivity(intent);

簡単な操作のためにバンドルを好まないでください。

編集:次に、他のアクティビティの onCreate 内:

    Bundle extras = getIntent().getExtras(); 
    if(extras !=null && extras.getInt("CAMPAIGN") == 1){
        newGame();
    }
    else{
        loadGame(extras.getInt("gameId"));
        //or whatever
    }
于 2012-06-09T08:33:30.387 に答える
0

戻るボタンの機能をオーバーライドして、メイン アクティビティを再起動し、それをゲーム アクティビティの上に設定して、ゲームに戻るときに同じことを行うことができます。しかし、ユーザーがゲームの開始ボタンをもう一度押すかどうかわからないため、これは間違いなく悪い習慣です。代わりに、onDestroy メソッドのアクティビティで使用されているすべてのリソースを解放し、ユーザーが戻ってきたときに新しいインスタンスを起動してみてください。また、使用するビットマップのサイズを最小限に抑えるようにしてください。例えば9パッチを試してみてください。

于 2012-06-09T08:34:39.153 に答える
0

単一のインスタンスのみを作成できるように、Android マニフェスト ファイルでアクティビティを定義する必要があります。

<activity
    android:launchMode="singleTask">
于 2012-06-09T08:38:00.747 に答える