Я работаю над приложением, в которое интегрирован LeakCanary. На протяжении всего моего приложения я получаю уведомление LeakCanary «Приложение замерзнет, Бррр ...». Теперь, если утечка постоянна, ее нельзя игнорировать. Итак, я просмотрел журналы и нашел их ниже.
├─ com.ilumi.fragments.ListFragment
│ Leaking: YES (Fragment#mFragmentManager is null)
│ ↓ ListFragment.mAddToList
├─ com.ilumi.widgets.CenteredLeftDrawableButton
│ Leaking: YES (ListFragment↑ is leaking and View.mContext references a destroyed activity)
│ mContext instance of com.ilumi.activities.DetailActivity with mDestroyed = true
│ View#mParent is set
│ View#mAttachInfo is null (view detached)
│ View.mWindowAttachCount = 1
│ ↓ CenteredLeftDrawableButton.mContext
╰→ com.ilumi.activities.DetailActivity
Leaking: YES (CenteredLeftDrawableButton↑ is leaking and Activity#mDestroyed is true and
Теперь, судя по всему, я решил, что проблема в CenteredLeftDrawableButton, который я использовал во многих местах своего приложения.
public class CenteredLeftDrawableButton extends AppCompatButton {
public CenteredLeftDrawableButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CenteredLeftDrawableButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CenteredLeftDrawableButton(Context context) {
super(context);
}
@Override
public void setCompoundDrawablePadding(int pad) {
super.setCompoundDrawablePadding(pad);
centerDrawables();
}
@Override
public void setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom) {
super.setCompoundDrawables(left, top, right, bottom);
centerDrawables();
}
@Override
public void setCompoundDrawablesRelativeWithIntrinsicBounds(int start, int top, int end, int bottom) {
super.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
centerDrawables();
}
@Override
public void setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable start, Drawable top, Drawable end, Drawable bottom) {
super.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
centerDrawables();
}
@Override
public void setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top, Drawable right, Drawable bottom) {
super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
centerDrawables();
}
@Override
public void setCompoundDrawablesWithIntrinsicBounds(int left, int top, int right, int bottom) {
super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
centerDrawables();
}
@Override
public void setCompoundDrawablesRelative(Drawable start, Drawable top, Drawable end, Drawable bottom) {
super.setCompoundDrawablesRelative(start, top, end, bottom);
centerDrawables();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
centerDrawables();
}
private void centerDrawables() {
Drawable[] compoundDrawables = getCompoundDrawables();
Drawable drawableLeft = compoundDrawables[0];
Drawable drawableRight = compoundDrawables[2];
if (drawableLeft != null || drawableRight != null) {
float textWidth = getPaint().measureText(getText().toString());
int drawablePadding = getCompoundDrawablePadding();
int drawableWidth = 0;
if (drawableLeft != null) {
drawableWidth += drawableLeft.getIntrinsicWidth();
}
if (drawableRight != null) {
drawableWidth += drawableRight.getIntrinsicWidth();
}
float bodyWidth = textWidth + drawableWidth + drawablePadding;
if (bodyWidth < getWidth()) {
float emptySpace = getWidth() - bodyWidth;
int paddingToLeftAndRight = (int) (emptySpace / 2);
setPadding(paddingToLeftAndRight, getPaddingTop(), paddingToLeftAndRight, getPaddingBottom());
}
}
}
public static void centerDrawables(TextView view) {
Drawable[] compoundDrawables = view.getCompoundDrawables();
Drawable drawableLeft = compoundDrawables[0];
Drawable drawableRight = compoundDrawables[2];
if (drawableLeft != null || drawableRight != null) {
float textWidth = view.getPaint().measureText(view.getText().toString());
int drawablePadding = view.getCompoundDrawablePadding();
int drawableWidth = 0;
if (drawableLeft != null) {
drawableWidth += drawableLeft.getIntrinsicWidth();
}
if (drawableRight != null) {
drawableWidth += drawableRight.getIntrinsicWidth();
}
float bodyWidth = textWidth + drawableWidth + drawablePadding;
if (bodyWidth < view.getWidth()) {
float emptySpace = view.getWidth() - bodyWidth;
int paddingToLeftAndRight = (int) (emptySpace / 2);
view.setPadding(paddingToLeftAndRight, view.getPaddingTop(), paddingToLeftAndRight, view.getPaddingBottom());
}
}
}
}
В каждом из приведенных ниже классов используются кнопки, которые я делаю.
private CenteredLeftDrawableButton mAddToSchedule;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mAddToSchedule = (CenteredLeftDrawableButton) view.findViewById(R.id.editScheduleButton);
mAddToSchedule.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Intent to open new screen
}
});
}
@Override
public void onResume() {
super.onResume();
if (someConditionTrue) {
mAddToList.setText(R.string.button_add_to_schedule);
mAddToList.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_add_circle_outline_black_24dp, 0, 0, 0);
} else {
mAddToList.setText(R.string.button_update_firmware);
mAddToList.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
}
}
Ничего тяжелого не происходит, за исключением добавления рисуемого элемента. Я не уверен, как это исправить. Если кто-то может помочь, это будет здорово.