我正在开发一个集成了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()
}

10-07 19:47