ラベル メモリリーク の投稿を表示しています。 すべての投稿を表示
ラベル メモリリーク の投稿を表示しています。 すべての投稿を表示

2018年10月1日月曜日

再びEditTextのメモリリーク

こんにちは。

以前にもEditTextでメモリリークを発見し対応したのですが、その後のライブラリのアップデートで改善されていました。

参考記事:「メモリリーク その4 EditText」

しかし、再び、別の原因によるEditTextのメモリリークが発生しました。

メモリリークが発生する場合と発生しない場合があり、しばらく気付かなかったため、どのライブラリから発生するのかは分かりません。

前回と同様、LeakCanaryで発見しました。

端末:Xperia performance
OS:Android 8.0.0

LeakCanaryより↓
In com.bnbnapp.bookshelf:3.13:3064.
* com.bnbnapp.bookshelf.ConditionActivity has leaked:
* GC ROOT static android.view.accessibility.AccessibilityNodeInfo.sPool
* references android.util.Pools$SynchronizedPool.mPool
* references array java.lang.Object[].[32]
* references android.view.accessibility.AccessibilityNodeInfo.mOriginalText
* references android.text.method.ReplacementTransformationMethod$SpannedReplacementCharSequence.mSpanned
* references android.text.SpannableStringBuilder.mSpans
* references array java.lang.Object[].[0]
* references android.widget.TextView$ChangeWatcher.this$0
* references android.support.v7.widget.AppCompatEditText.mContext
* leaks com.bnbnapp.bookshelf.ConditionActivity instance
 
こちらの対応は以下。

上記対応すると以下のメモリリークを検出しました。

LeakCanaryより↓
In com.bnbnapp.bookshelf:3.13:3064.
* com.bnbnapp.bookshelf.ConditionActivity has leaked:
* GC ROOT static android.view.accessibility.AccessibilityNodeInfo.sPool
* references android.util.Pools$SynchronizedPool.mPool
* references array java.lang.Object[].[5]
* references android.view.accessibility.AccessibilityNodeInfo.mOriginalText
* references android.text.method.ReplacementTransformationMethod$SpannedReplacementCharSequence.mSpanned
* references android.text.SpannableStringBuilder.mFilters
* references array android.text.InputFilter[].[0]
* references android.widget.Editor$UndoInputFilter.mEditor
* references android.widget.Editor.mProcessTextIntentActionsHandler
* references android.widget.Editor$ProcessTextIntentActionsHandler.mContext
* leaks com.bnbnapp.bookshelf.ConditionActivity instance
 
こちらの対応は以下。

以上で、メモリリークは検出されなくなりました。

2018年1月19日金曜日

メモリリーク その4 EditText

こんにちは。

現在までに発見したメモリリークの最終記事です。


compileSdkVersionを26に上げたところ、LeakCanaryでメモリリークを検出しました。

検出端末は、Xperia performanceです。

そのときのLeakCanaryのスクリーンショットが以下です。


LeakCanary

InputConnectionWrapperのmTargetが解放されないようです。

よって、上記が解放されるように対応しました。

まず、EditTextの代わりに自作のMyEditTextを用意しました。
次に、InputConnectionWrapperも自作し、closeConnectionでmTargetをnullにします。

以上により、メモリリークは検出されなくなりました。


2017年10月31日火曜日

メモリリーク その3 AdMob広告の表示で

こんにちは。



AdMobの広告を表示させるために、AdMobの以下のガイドに沿ってソースを修正しました。

https://developers.google.com/admob/android/quick-start?hl=ja


ガイドより↓

しかし、これだとメモリリークを起こします。


以前にも書きましたが、ActivityのContextを渡し、そのContextを保持されてしまうとActivityを解放できません。

ApplicationContextを渡せば、Activityはメモリリークを起こしません。

また、MobileAds.initializeは、一回だけで良いと上記のガイドに記述があるので、ApplicationのonCreateで呼び出すようにしました。

なぜなら、MainActivityのonCreateは、一回だけ呼び出されるとは限りません。起動時以外にも、画面を回転させると呼び出されます。

以下のように修正しました。



以上です。


2017年10月12日木曜日

メモリリーク その2 AlertDialog

こんばんは。

今回もメモリリークについてです。

AlertDialogで、メモリリークが発生していました。

そもそも、使い方を誤っていました。

以下のようにすれば、簡単にメッセージダイアログが表示できますが、これではいけません。



画面を回転した場合などに、メモリリークが発生します。

Androidデベロッパーのページにも書かれていました。

https://developer.android.com/guide/topics/ui/dialogs.html?hl=ja

DialogFragmentを使ってダイアログを管理すると、ライフサイクルイベントが正しく処理されると書かれています。

個人のブログで、AlertDialogの使い方を見てコーディングしたのですが、ある程度コーディングした後に、上記のページを見つけました。

そして、実際にメモリリークするか調査してみると、しっかりとメモリリークしていました。

全てのAlertDialogを修正とテストするのは大変でした。

それから、ネットで検索する場合は、Androidデベロッパーのページや、リファレンスを最初に読むようにしています。

DialogFragmentを使ったAlertDialogのコーディング方法は、上記のページを参考にしてください。


2017年10月11日水曜日

メモリリーク その1

こんばんは。

忙しくて、なかなか更新できませんでした。

前回メモリリークを調査した結果、検出した内容です。

今回は、単純なコーディングミスです。

Staticな変数に、Contextを渡したクラスのインスタンスを保持しているのですが、ContextにActivityをキャストしたContextを渡していました。


ソースで説明します。


ToastクラスのインスタンスをContextを渡して作成し、Staticな変数で保持しています。
上記のshowToastを以下のように呼び出していたのです。


上記の例は、Activityで呼び出していたので、thisは、Activityです。

Contextは、ApplicationかActivityをと書かれていますので、以下のように変更したら、メモリリークはなくなりました。


Staticな変数は、要注意です。

2017年9月3日日曜日

メモリリーク調査


こんばんは。お久しぶりです。

ブログは更新していませんでしたが、開発は行っています。


ふと、メモリリークはしていないのか気になって、調査してみることにしました。

確保された領域は、どこからも参照されなくなれば、GC(ガベージコレクション)でシステムが勝手に解放してくれます。

参照をなくした後にGCを強制的に行い、解放が行われているかチェックすれば、メモリリークを見つけられます。


Android Studioでデバッグ中に、Android Monitorで、一連のチェックが行えます。




上のAndroid Monitorの赤で囲った部分の一番左のアイコンをクリックすると、GCが行われます。

真ん中のアイコンをクリックすると、メモリの状態が記録されます。


あるいは、Leakcanaryというライブラリを使用してもチェックできます。

Leakcanaryは、https://github.com/square/leakcanaryにあります。

やり方も記載されていますが、一点、はまったことがあります。

全く、メモリリークが検出されないのです。メモリリークが元々なかったのかと一瞬思いましたが、チェック自体が走った形跡もなかったので、ライブラリのソースを追ってみました。

なんと、デバッグでアタッチしている場合は、チェックしないようになっていました。

私、USBで繋いで、ばりばりデバッグアタッチしていました。

なので、スマホにデバッグ版をインストールした状態で、アイコンをタップしてアプリを単体で動かしたところ、メモリリークが無事?、検出されました。

Activityを閉じたときにチェックしています。


メモリリークの内容は、後日書こうと思います。