1

PDFTronを使ったアプリを開発中です。割り当てられたメモリを表示するアクティビティを開くと、大幅に増加することに気付きました。アクティビティから離れた後、メモリの一部だけが再び解放されます。一部の PDFtron パーツが取り残されています。

ここに画像の説明を入力

問題は、アクティビティを NoHistory と singleTask に設定したにもかかわらず、アクティビティが終了していないように見えることです。メモリ管理に関するいくつかのコースを見てきましたが、アクティビティが開いたままになる原因がわかりません。

アクティビティを呼び出す前にFinish();、PdfViewCtrl を破棄します。次に、OnDestroy で:

protected override void OnDestroy()
{
    base.OnDestroy();
    if (_mPdfViewCtrl == null) return;
    _mPdfViewCtrl.Destroy();
    _mPdfViewCtrl = null;
}

アプリを長期間使用すると、メモリ不足エラーが発生します。

--- End of managed Java.Lang.Error stack trace ---
 java.lang.OutOfMemoryError
 dalvik.system.NativeStart.run(Native Method):0

また

    --- End of managed Java.Lang.Error stack trace ---
 java.lang.OutOfMemoryError
 android.graphics.Bitmap.nativeCreate(Native Method):0
 android.graphics.Bitmap.createBitmap(Bitmap.java:726):0
 android.graphics.Bitmap.createBitmap(Bitmap.java:703):0
 android.graphics.Bitmap.createBitmap(Bitmap.java:670):0
 pdftron.PDF.Utils.SignaturePickerDialog$SignatureView.onSizeChanged(SignaturePickerDialog.java:244):0
 android.view.View.sizeChange(View.java:15326):0
 android.view.View.setFrame(View.java:15290):0
 android.view.View.layout(View.java:15201):0
 android.widget.RelativeLayout.onLayout(RelativeLayout.java:1076):0
 android.view.View.layout(View.java:15204):0
 android.view.ViewGroup.layout(ViewGroup.java:4793):0
 android.widget.FrameLayout.onLayout(FrameLayout.java:448):0
 android.view.View.layout(View.java:15204):0
 android.view.ViewGroup.layout(ViewGroup.java:4793):0
 android.widget.RelativeLayout.onLayout(RelativeLayout.java:1076):0
 android.view.View.layout(View.java:15204):0
 android.view.ViewGroup.layout(ViewGroup.java:4793):0
 android.widget.FrameLayout.onLayout(FrameLayout.java:448):0
 android.view.View.layout(View.java:15204):0
 android.view.ViewGroup.layout(ViewGroup.java:4793):0
 android.widget.FrameLayout.onLayout(FrameLayout.java:448):0
 android.view.View.layout(View.java:15204):0
 android.view.ViewGroup.layout(ViewGroup.java:4793):0
 android.widget.LinearLayout.setChildFrame(LinearLayout.java:1677):0
 android.widget.LinearLayout.layoutVertical(LinearLayout.java:1531):0
 android.widget.LinearLayout.onLayout(LinearLayout.java:1440):0
 android.view.View.layout(View.java:15204):0
 android.view.ViewGroup.layout(ViewGroup.java:4793):0
 android.widget.FrameLayout.onLayout(FrameLayout.java:448):0
 android.view.View.layout(View.java:15204):0
 android.view.ViewGroup.layout(ViewGroup.java:4793):0
 android.widget.LinearLayout.setChildFrame(LinearLayout.java:1677):0
 android.widget.LinearLayout.layoutVertical(LinearLayout.java:1531):0
 android.widget.LinearLayout.onLayout(LinearLayout.java:1440):0
 android.view.View.layout(View.java:15204):0
 android.view.ViewGroup.layout(ViewGroup.java:4793):0
 android.widget.FrameLayout.onLayout(FrameLayout.java:448):0
 android.view.View.layout(View.java:15204):0
 android.view.ViewGroup.layout(ViewGroup.java:4793):0
 android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2263):0
 android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2009):0
 android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1251):0
 android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6379):0
 android.view.Choreographer$CallbackRecord.run(Choreographer.java:791):0
 android.view.Choreographer.doCallbacks(Choreographer.java:591):0
 android.view.Choreographer.doFrame(Choreographer.java:561):0
 android.view.Choreographer$FrameHandler.handleMessage(Choreographer.java:693):0
 android.os.Handler.dispatchMessage(Handler.java:99):0
 android.os.Looper.loop(Looper.java:137):0
 android.app.ActivityThread.main(ActivityThread.java:5493):0
 java.lang.reflect.Method.invokeNative(Native Method):0
 java.lang.reflect.Method.invoke(Method.java:525):0
 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1209):0
 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1025):0
 dalvik.system.NativeStart.main(Native Method):0

シミュレートされたセッション (Android Studio のモニタリング) からの印刷画面の下: ここに画像の説明を入力

編集された OnDestroy:

        var old_tool = _mPdfViewCtrl.ToolManager;
        var old_doc = _mPdfViewCtrl.Doc;
        _mPdfViewCtrl?.CloseDoc();
        _mPdfViewCtrl?.CloseTool();
        _mPdfViewCtrl?.Destroy();
        _mPdfViewCtrl = null;
        _mPdfViewCtrl?.Dispose();
        if (old_doc != null)
        {
            old_doc.Dispose();
        }

        if (old_tool != null)
        {
            old_tool.Dispose();
        }

ここに画像の説明を入力

4

2 に答える 2

3

このリンクから:

「Q: ユーザーがファイルを選択するページと、ユーザーが選択した PDF を表示する別のページがあります。ユーザーが PDF 表示ページからファイル ページに戻るときに、PDFNet によって使用されるリソースをクリーンアップしたいと考えています。ツール、PDFViewCtrl、および PDFDoc をクリーンアップする正しい順序。

A: 最初に PDFViewCtrl.CloseDoc() を呼び出す必要があります。その後、PDFDoc.Dispose() を呼び出すことができます。これは、どのページでも PDFViewCtrl を使用する場合に OnNavigatedFrom に配置するのに適しています。

また、PDFViewCtrl を手動で破棄することはできません。代わりに、基になる構造をすべて削除する PDFViewCtrl.FreeResources を追加しました。

以下を追加したい:

        PDFDoc doc = this.PDFViewCtrl.GetDoc();

        this.PDFViewCtrl.CloseDoc();


        if (doc != null)
        {
            await CloseDocAsync(doc);
        }

        this.PDFViewCtrl.FreeResources();

CloseDocAsync は、バックグラウンド スレッドで doc.Dispose を呼び出すだけです (大規模で複雑なドキュメントの場合)。私が知っているすべてのドキュメントはかなり迅速に破棄されるため、これは必要ないかもしれません。でも痛くない。UI スレッドでの 200 ミリ秒の遅延でさえ、混乱を招く可能性があります。

注意すべきことの 1 つは、ガベージ コレクターが PDFViewCtrl を再利用するには、それに登録されているすべてのイベントを登録解除する必要があることです。そのため、ページから離れたときにも ToolManager.Dispose() を呼び出す必要があります。その場合は、上で追加したコードの前に ToolManager.Dispose を呼び出してください。」

上記のいずれでも解決しない場合は、質問を PDFTronフォーラムに再投稿してみてください。同社には、優先技術サポートを提供する技術サポート オプションもあります。使用しているバージョンによっては、技術サポートが無料の場合があります。

編集

ドキュメント用に提供したリンクは、Android 用ではなく、Windows バージョン用でした。PDFViewCtrlおよびPDFDocの Android バージョンのリンクは次のとおりです。

したがって、上記のリンクのコードは機能しません。代わりに、単にドキュメントを閉じることをお試しください。PDFViewCtrl クラスから呼び出すことができる CloseDoc メソッドがあります。これが機能しない場合は、PDFDoc メソッドから Close メソッドを呼び出してみてください。PDFViewCtrl クラスには、現在のドキュメント (PDFDoc) を返す getDoc というメソッドがあります。ドキュメントによると、PDFDoc.close メソッドはデストラクタです。というわけで、この2つのアイデアを試してみてください。

もう 1 つ気づいたことは、PDFViewCtrl クラスに lock メソッドと unlock メソッドがあることです。上記の 2 つのアイデアがうまくいかない場合は、close メソッドを呼び出す前に docUnlock メソッドを呼び出してみてください。ドキュメントがロックされている場合、閉じる呼び出しがハングするか、タイムアウトする可能性があるという考えです。

さて、それがうまくいかない場合、あなたがしていることは他に何かありますか? あなたやあなたのグループの他の誰かが、あなたがしている他のことのためにメモリをクリーンアップするのを忘れている可能性はありますか? C++ を使用している、または C++ を使用する API を使用していて、メモリの削除を怠ったり、適切にクリーンアップするために適切な close メソッドを呼び出したりしている人はいますか?

プロファイラーを使用すると、これらの質問に答えることができます。サード パーティ製のプロファイラーを利用するか、Microsoft .NET Memory Analyzerを試すことができます。Androidで動くかどうかはわかりません。また、バージョン 4.5 以降の .NET Framework も必要です。

Xamarin プロファイラーもあります。これは、おそらく最初に選択する方がよいでしょう。

于 2016-10-04T06:24:26.263 に答える
1

アクティビティに PDFDoc オブジェクトへの参照もある場合は、それも破棄する必要があります。これが推奨される方法です。

protected override void OnDestroy()
{
    base.OnDestroy();
    if (_mPdfViewCtrl == null) return;
    _mPdfViewCtrl.Destroy();
    _mPdfViewCtrl = null;
    if(_mPdfDoc != null)
    {
        _mPdfDoc.Dispose();
    }
}

またはより一般的に

protected override void OnDestroy()
{
    base.OnDestroy();
    if (_mPdfViewCtrl == null) return;
    PDFDoc old_doc = _mPdfViewCtrl.Doc;
    _mPdfViewCtrl.Destroy();
    _mPdfViewCtrl = null;
    if(old_doc != null)
    {
        old_doc.Dispose();
    }
}
于 2016-10-03T17:41:23.943 に答える