【问题标题】:Simple Android App - Out of Memory error when running on smartphone简单的 Android 应用程序 - 在智能手机上运行时出现内存不足错误
【发布时间】:2017-02-05 14:24:58
【问题描述】:

我对 Android Studio 还很陌生,我尝试制作一个简单的应用程序。单击按钮后应出现随机图像。下一个不能是已经显示的。

我有两节课。 MainActivity 和 RandomCardDraw。

当我在 AVD 模拟器中运行应用程序时,它不会崩溃。但有时我会收到“跳过帧”的信息。当我在三星 S6 上运行它时,每次尝试获取第二张图像时应用程序都会崩溃。在 Android 中,我可以看到内存不足错误。

图片大小在 100-200kb 之间,我有大约 18 张。

也许您可以看到我的性能问题是从哪里得到的?

这是我的代码:

主活动:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;



public class MainActivity extends AppCompatActivity {

    ImageView cardView;
    Button nextCard;
    RandomCardDraw2 game1 = new RandomCardDraw2();
    int counter = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        game1.createRandomCardList();
        gameStart();


    }

    public void gameStart()
    {
        cardView = (ImageView) findViewById(R.id.cardView);
        nextCard = (Button) findViewById(R.id.nextCard);
        nextCard.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v)
            {

                if (counter < 19)
                {
                    int id = getResources().getIdentifier(game1.drawnCards.get(counter), "drawable", getPackageName());
                    cardView.setImageResource(id);
                    counter++;
                }

            }
        });

    }

}

还有 RandowmCardDraw:

 import java.util.ArrayList;
 import java.util.Random;  


public class RandomCardDraw2
{
    ArrayList<String> drawnCards = new ArrayList<>();
    Random rndInt = new Random();

    public void createRandomCardList()
    {
        boolean gameType = true;
        int counter;
        if (gameType == true)
        {
            counter = 19;
            for (int i = 0; i < counter; i++)
            {
                String cardId = "card" + rndInt.nextInt(18 + 1);
                drawnCards.add(cardId);
            }
        }
        else
        {
            counter = 23;
            for (int i = 0; i < counter; i++)
            {
                String cardId = "card" + rndInt.nextInt(18 + 1);
                drawnCards.add(cardId);
            }
        }

    }
}

应用打开时。带有卡片的 ArrayList 是随机填充的。然后当用户单击按钮时,会出现下一张卡片。正如我所说,在我的智能手机上,当我想要获取第二张图片时,应用程序崩溃了。

错误代码:

E/AndroidRuntime: FATAL EXCEPTION: main
              Process: com.example.kajet.shutupanddrink, PID: 18109
              java.lang.OutOfMemoryError: Failed to allocate a 192000012 byte allocation with 16775360 free bytes and 69MB until OOM
                  at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
                  at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
                  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:856)
                  at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:675)
                  at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:2228)
                  at android.content.res.Resources.loadDrawableForCookie(Resources.java:4215)
                  at android.content.res.Resources.loadDrawable(Resources.java:4089)
                  at android.content.res.Resources.getDrawable(Resources.java:2005)
                  at android.content.res.Resources.getDrawable(Resources.java:1987)
                  at android.support.v7.widget.ResourcesWrapper.getDrawable(ResourcesWrapper.java:133)
                  at android.content.Context.getDrawable(Context.java:464)
                  at android.support.v4.content.ContextCompatApi21.getDrawable(ContextCompatApi21.java:26)
                  at android.support.v4.content.ContextCompat.getDrawable(ContextCompat.java:321)
                  at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:202)
                  at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:192)
                  at android.support.v7.widget.AppCompatImageHelper.setImageResource(AppCompatImageHelper.java:66)
                  at android.support.v7.widget.AppCompatImageView.setImageResource(AppCompatImageView.java:71)
                  at com.example.kajet.shutupanddrink.MainActivity$1.onClick(MainActivity.java:41)
                  at android.view.View.performClick(View.java:5702)
                  at android.widget.TextView.performClick(TextView.java:10888)
                  at android.view.View$PerformClick.run(View.java:22541)
                  at android.os.Handler.handleCallback(Handler.java:739)
                  at android.os.Handler.dispatchMessage(Handler.java:95)
                  at android.os.Looper.loop(Looper.java:158)
                  at android.app.ActivityThread.main(ActivityThread.java:7229)
                  at java.lang.reflect.Method.invoke(Native Method)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

谁能帮忙?

非常感谢!

【问题讨论】:

  • 请发布您的堆栈跟踪...!
  • 嗨,sobhit,感谢您的提示。我对其进行了编辑并将错误代码放在我的问题中。我希望这就是你所说的stacktrace!
  • images are between 100-200kb。它们是什么样的图像?他们的解决方案是什么?
  • 阅读您的堆栈跟踪。您可以清楚地看到它以 OnClick() 开头,而 cardView.setImageResource(id); 是罪魁祸首,因为它使用 BitmapFactory.decodeResourceStream 会导致 Bitmap 对于可用内存来说变得太大。 (从底部到顶部读取堆栈跟踪)。
  • on my smartphone the app crashes。如果您捕获 OutOfMemoryError,您的应用程序不必崩溃。您可以使用 e.getMessage() 信息向用户显示 Toast()。

标签: java android out-of-memory


【解决方案1】:

在您的清单中添加这些行:

android:hardwareAccelerated="false"
android:largeHeap="true"

@你的 manifest.xml 会是:

<application
android:allowBackup="true"
android:hardwareAccelerated="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:largeHeap="true"
android:supportsRtl="true"
android:theme="@style/AppTheme">

【讨论】:

  • 感谢您的回答。我明天测试一下。从声明来看,这是否只是让应用程序获得更多 RAM?我的意思是我想要一个不占用 500MB RAM 的高效应用程序。抽一张卡时,我的手机显示应用程序使用了 200MB 的 RAM ......
  • 实际上 android:largeHeap 是增加分配给应用程序内存的工具。没有明确定义需要使用此标志。如果您需要更多内存 - Android 为您提供了增加内存的工具。
  • 好的,谢谢。至少它现在有效。由于我的错误来自 BitmapFactory,是否可以 recycle() Bitmap 以节省内存?如果是,怎么做?
  • 如果您觉得这个答案有用,可以采纳吗?
猜你喜欢
  • 2021-07-11
  • 2012-11-20
  • 2015-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-01
  • 1970-01-01
相关资源
最近更新 更多