0

このアプリは問題なく動作していましたが、遅すぎました。1つのUIスレッドですべてを実行していましたが、gridViewに多数の画像が読み込まれたページでは、ページが読み込まれるまでに長い遅延が発生していました。「UIスレッドからビットマップを処理する」というAndroidドキュメントのコードを使用してこの問題を修正しました

このコードを使用すると、グリッドビューページが高速で読み込まれ、各小さなビットマップ画像が個別のバックグラウンドスレッドに1つずつ読み込まれることがわかります。

マルチスレッド部分にAsyncTaskを使用するこのコードでは、いくつかのメソッドを使用してイメージサイズを縮小し、メモリ不足エラーを排除します。このプログラムの以前のシングルスレッドバージョンで使用したのと同じ画像縮小方法。画像がどんなに大きくても、画像縮小法で設定した200dp×200dpを超えてはいけません。マルチスレッドなしの古いバージョンのアプリで動作し、新しいバージョンのアプリではほとんど問題ないように見えます。しかし、奇妙な問題があります。

BitmapFactoryデコードメソッドに関連するメモリエラーが発生しています。

これがどのように発生するかというと、私は多くの小さな画像でアプリのテストを開始し、そこに1つの大きな画像を約10,000X10,000ピクセルのビットマップに配置しました。ビットマップファクトリオプションを使用して画像が縮小されているため、問題が発生することはありません。

エラーはすぐには発生しません。アプリはしばらくは正常に動作しますが、アクティビティ間を移動したり行ったりした後は正常に動作します。3〜5分後にクラッシュします。

他にこのような問題を抱えている人はいますか?そして、私がチェックできる原因となる可能性のあるアイデアを提供できますか?または私が正しい方向を見始めるのを手伝ってください?

画像縮小コードを以下に示します。その下にlogcat出力があります。

    class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
    private final WeakReference<ImageView> imageViewReference;
    private String data = "";

    public BitmapWorkerTask(ImageView imageView) {
        // Use a WeakReference to ensure the ImageView can be garbage collected
        imageViewReference = new WeakReference<ImageView>(imageView);
    }

    // Decode image in background.
    @Override
    protected Bitmap doInBackground(String... params) {
        data = params[0];
       // return imageProcessor(data);
        return decodeSampledBitmapFromResource(data, 100, 100);
    }

    // Once complete, see if ImageView is still around and set bitmap.
    @Override
    protected void onPostExecute(Bitmap bitmap) {
        if (imageViewReference != null && bitmap != null) {
            final ImageView imageView = imageViewReference.get();
            if (imageView != null) {
                imageView.setImageBitmap(bitmap);
            }
        }
    }
  }// end BitmapWorkerTask extends AsyncTask class

      public static Bitmap decodeSampledBitmapFromResource(String fileName, int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(fileName, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;

    return BitmapFactory.decodeFile(fileName, options);


}//end decodeSampledBitmapfromresource method


public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;

if (height > reqHeight || width > reqWidth) {
    if (width > height) {
        inSampleSize = Math.round((float)height / (float)reqHeight);
    } else {
        inSampleSize = Math.round((float)width / (float)reqWidth);
    }
}
return inSampleSize;
}// end calculateInSampleSize method


Logcat

17:52:28.340: E/AndroidRuntime(7812): FATAL EXCEPTION: main
17:52:28.340: E/AndroidRuntime(7812): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.v.splitter/com.v.splitter.AudioViewer}: android.view.InflateException: Binary XML file line #63: Error inflating class <unknown>
17:52:28.340: E/AndroidRuntime(7812): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956)
17:52:28.340: E/AndroidRuntime(7812): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
17:52:28.340: E/AndroidRuntime(7812): at android.app.ActivityThread.access$600(ActivityThread.java:123)
17:52:28.340: E/AndroidRuntime(7812): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
17:52:28.340: E/AndroidRuntime(7812): at android.os.Handler.dispatchMessage(Handler.java:99)
17:52:28.340: E/AndroidRuntime(7812): at android.os.Looper.loop(Looper.java:137)
17:52:28.340: E/AndroidRuntime(7812): at android.app.ActivityThread.main(ActivityThread.java:4424)
17:52:28.340: E/AndroidRuntime(7812): at java.lang.reflect.Method.invokeNative(Native Method)
17:52:28.340: E/AndroidRuntime(7812): at java.lang.reflect.Method.invoke(Method.java:511)
17:52:28.340: E/AndroidRuntime(7812): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
17:52:28.340: E/AndroidRuntime(7812): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
17:52:28.340: E/AndroidRuntime(7812): at dalvik.system.NativeStart.main(Native Method)
17:52:28.340: E/AndroidRuntime(7812): Caused by: android.view.InflateException: Binary XML file line #63: Error inflating class <unknown>
17:52:28.340: E/AndroidRuntime(7812): at android.view.LayoutInflater.createView(LayoutInflater.java:606)
17:52:28.340: E/AndroidRuntime(7812): at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
17:52:28.340: E/AndroidRuntime(7812): at android.view.LayoutInflater.onCreateView(LayoutInflater.java:653)
17:52:28.340: E/AndroidRuntime(7812): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:678)
17:52:28.340: E/AndroidRuntime(7812): at android.view.LayoutInflater.rInflate(LayoutInflater.java:739)
17:52:28.340: E/AndroidRuntime(7812): at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
17:52:28.340: E/AndroidRuntime(7812): at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
17:52:28.340: E/AndroidRuntime(7812): at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
17:52:28.340: E/AndroidRuntime(7812): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:255)
17:52:28.340: E/AndroidRuntime(7812): at android.app.Activity.setContentView(Activity.java:1835)
17:52:28.340: E/AndroidRuntime(7812): at com.v.splitter.AudioViewer.onCreate(AudioViewer.java:63)
17:52:28.340: E/AndroidRuntime(7812): at android.app.Activity.performCreate(Activity.java:4465)
17:52:28.340: E/AndroidRuntime(7812): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
17:52:28.340: E/AndroidRuntime(7812): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
17:52:28.340: E/AndroidRuntime(7812): ... 11 more
17:52:28.340: E/AndroidRuntime(7812): Caused by: java.lang.reflect.InvocationTargetException
17:52:28.340: E/AndroidRuntime(7812): at java.lang.reflect.Constructor.constructNative(Native Method)
17:52:28.340: E/AndroidRuntime(7812): at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
17:52:28.340: E/AndroidRuntime(7812): at android.view.LayoutInflater.createView(LayoutInflater.java:586)
17:52:28.340: E/AndroidRuntime(7812): ... 24 more
12-17:52:28.340: E/AndroidRuntime(7812): Caused by: java.lang.OutOfMemoryError
17:52:28.340: E/AndroidRuntime(7812): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
17:52:28.340: E/AndroidRuntime(7812): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:483)
17:52:28.340: E/AndroidRuntime(7812): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:351)
17:52:28.340: E/AndroidRuntime(7812): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:773)
17:52:28.340: E/AndroidRuntime(7812): at android.content.res.Resources.loadDrawable(Resources.java:1937)
17:52:28.340: E/AndroidRuntime(7812): at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
17:52:28.340: E/AndroidRuntime(7812): at android.view.View.<init>(View.java:2785)
17:52:28.340: E/AndroidRuntime(7812): at android.view.View.<init>(View.java:2722)
17:52:28.340: E/AndroidRuntime(7812): at android.view.ViewGroup.<init>(ViewGroup.java:379)
17:52:28.340: E/AndroidRuntime(7812): at android.widget.RelativeLayout.<init>(RelativeLayout.java:174)
17:52:28.340: E/AndroidRuntime(7812): ... 27 more
4

1 に答える 1

2

BitmapFactoryのサイズを変更するには、10,000x10,000の画像をロードする必要があります。その画像を小さくすることをお勧めします。

とにかく、多くのビットマップを使用している場合は、使い終わったら必ずリサイクルしてください。それらは、ガベージコレクションに到達するのに時間がかかるネイティブリソースを消費します。

bitmap.recycle();

例外がスローされるため、リサイクル後にビットマップを使用しないように注意してください。

于 2012-12-10T11:22:17.070 に答える