我正在开发一个集成了LeakCanary的应用程序。在我的整个应用程序中,我不断收到LeakCanary通知“应用程序将冻结,Brrr ...”。现在,如果泄漏是一致的,则不能忽略。因此,我浏览了日志并在下面找到。
├─ 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);
}
}
除了添加了drawable之外,没有其他事情发生。我不确定如何解决此问题。如果有人可以帮助,那就太好了。
最佳答案
这可能会有所帮助:
您要在mAddToSchedule
上设置一个单击侦听器,并且在销毁后不要将其删除,因此它保留了CenteredLeftDrawableButton
的引用,您可以像这样在片段中删除它:
@Override
public void onDestory() {
mAddToSchedule.setOnClickLister(null)
super.onDestory()
}