java - 匿名实现导致内存泄漏

标签 java android memory-management memory-leaks leakcanary

我正在使用 leak canary 来检测内存泄漏,我必须说这是一个非常好的库来检测潜在的内存泄漏,下面是它生成的泄漏报告。我无法找到如何删除这个匿名实现。

GoProFragment 已泄露:

  • GC ROOT java.util.Timer$TimerImpl.
  • references MainActivity$5.this$0 (anonymous subclass of java.util.TimerTask)
  • references MainActivity.mHelper
  • references IabHelper.mPurchaseListener
  • references GoProFragment$2.this$0 (anonymous implementation of IabHelper$OnIabPurchaseFinishedListener)
  • GoProFragment instance
**GoProFragment.java**
public class GoProFragment extends BaseFragment {

    @Bind(R.id.btn_subscription_yearly)
    Button btnsubScriptionYearly;
    @Bind(R.id.btn_subscription_monthly)
    Button monthly;
    private ProgressDialog progressDialog;
    String product_price_one, product_price_two, product_price_three;
    @Bind(R.id.subscription_type)
    TextView subScriptionType;
    @Bind(R.id.graph_paid_feature)
    ImageView imageView;
    Bitmap icon;


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.pro_layout, container, false);
        ButterKnife.bind(this, view);
        setHasOptionsMenu(true);
        activity.preferences.setDisplayUpgrade(false);
        icon = BitmapFactory.decodeResource(activity.getResources(), R.drawable.subscription_img_two);
        imageView.setImageBitmap(icon);
        subScriptionType.setText(activity.preferences.getSubscriptionType());
        String[] sku = { Util.SKU_CHALLENGE,  Util.SKU_SUBSCRIPTION,  Util.SKU_YEAR_SUBSCRIPTION};
        if(isNetworkAvailable(activity)) {
            activity.mHelper.queryInventoryAsync(true, Arrays.asList(sku), mGotInventoryListener);
            showProgressDialog();
        }
        if (activity.preferences.isHasSubscription()) {
            /*btnsubScriptionYearly.setVisibility(View.GONE);
            monthly.setVisibility(View.GONE);*/
        }
        return view;
    }
    IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
        @Override
        public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
            dismissProgressDialog();
            product_price_one = inventory.getSkuDetails( Util.SKU_SUBSCRIPTION).getPrice();
            product_price_two = inventory.getSkuDetails( Util.SKU_YEAR_SUBSCRIPTION).getPrice();
            product_price_three = inventory.getSkuDetails( Util.SKU_CHALLENGE).getPrice();
            monthly.setVisibility(View.VISIBLE);
            btnsubScriptionYearly.setVisibility(View.VISIBLE);
            monthly.setText(activity.getString(R.string.monthly_subscription_text, product_price_one));
            btnsubScriptionYearly.setText(activity.getString(R.string.yearly_subscription_text, product_price_two));

        }

    };

    @OnClick(R.id.btn_subscription_monthly)
    public void onSubscription() {
        if (Validator.isNotNull(activity.mHelper)) {
            if (!activity.mHelper.subscriptionsSupported()) {
                 Util.showToast(activity, getString(R.string.subscription_not_supported));
                return;
            }
            if (!activity.mHelper.getAsyncInProgress()) {
                activity.mHelper.launchPurchaseFlow(activity,
                         Util.SKU_SUBSCRIPTION, IabHelper.ITEM_TYPE_SUBS,
                         Util.RC_REQUEST, mPurchaseFinishedListener,  Util.PAYLOAD);
            }
        }
    }

    @OnClick(R.id.btn_subscription_yearly)
    public void onYearSubscription() {
        if (Validator.isNotNull(activity.mHelper)) {
            if (!activity.mHelper.subscriptionsSupported()) {
                 Util.showToast(activity, getString(R.string.subscription_not_supported));
                return;
            }
            if (!activity.mHelper.getAsyncInProgress()) {
                activity.mHelper.launchPurchaseFlow(activity,
                         Util.SKU_YEAR_SUBSCRIPTION, IabHelper.ITEM_TYPE_SUBS,
                         Util.RC_REQUEST, mPurchaseFinishedListener,  Util.PAYLOAD);
            }
        }
    }

    private boolean isNetworkAvailable(Context context) {
        final ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivity != null) {
            NetworkInfo[] info = connectivity.getAllNetworkInfo();
            if (info != null)
                for (int i = 0; i < info.length; i++)
                    if (info[i].getState() == NetworkInfo.State.CONNECTED) {
                        return true;
                    }
        }

        return false;
    }
    IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
        public void onIabPurchaseFinished(IabResult result, Purchase purchase) {

            // if we were disposed of in the meantime, quit.
            if (activity.mHelper == null) {
                return;
            }

            if (result.isFailure()) {
                return;
            }
            if (! Util.verifyDeveloperPayload(purchase)) {
                return;
            }
            if (purchase.getSku().equals( Util.SKU_SUBSCRIPTION)) {
                // bought the infinite gas subscription
                setPremium(purchase, Calendar.MONTH);
            } else if (purchase.getSku().equals( Util.SKU_YEAR_SUBSCRIPTION)) {
                // bought the infinite gas subscription
                setPremium(purchase, Calendar.YEAR);
            }
        }
    };
    public void setPremium(Purchase purchase, int duration) {
        if ( Util.verifyDeveloperPayload(purchase)) {
            activity.preferences.setHasSubscription(true);
            if (Validator.isNotNull(activity.adView)) {
                activity.adView.setVisibility(View.GONE);
            }
             Util.showToast(activity, getString(R.string.upgraded_successfully));
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date(purchase.getPurchaseTime()));
            calendar.add(duration, 1);
            activity.preferences.getUserInfo().setSubscriptionEndOn(calendar.getTime());
            if(purchase.getSku().equals( Util.SKU_SUBSCRIPTION))
            {
                activity.preferences.setSubscriptionType(activity.getResources().getString(R.string.monthly));
            }
            else {
                activity.preferences.setSubscriptionType(activity.getResources().getString(R.string.yearly));
            }
            activity.preferences.getUserInfo().setPremium(true);
            //subscriptionEndOn.setText(dateFormat.format(activity.preferences.getUserInfo().getSubscriptionEndOn()));
        }
    }

    private void showProgressDialog() {
        if (!activity.isFinishing() && progressDialog == null) {
            progressDialog = new ProgressDialog(activity,R.style.CustomProgressDialog);
            progressDialog.setCancelable(false);
            progressDialog.show();

        }

    }

    /**
     * dismiss Progress Dialog.
     */
    private void dismissProgressDialog() {
        if (!activity.isFinishing() && progressDialog != null && progressDialog.isShowing()) {
            progressDialog.dismiss();
            progressDialog=null;
        }
    }

    @Override
    public void onDetach() {
        if(Validator.isNotNull(icon)){
            icon.recycle();
        }
        super.onDetach();
    }

最佳答案

我不认为这是一个问题。您可以在 Fragment 中保留状态,但您应该在 onCreate 回调中调用 setRetainInstance(true);

参见 this article

或者,您可以在 onDetach 回调中设置字段 mGotInventoryListener = null;

关于java - 匿名实现导致内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39225151/

相关文章:

iphone - iOS SDK : Adding AVCaptureVideoDataOutput to AVCaptureSession causes it to slowly leak memory indefinitely

java - 运行 GWT Map 时出错 - Maps key 是否丢失或无效?

java - 暂停和恢复正在 hibernate 的 Java 线程

java - jpa,尝试从实体创建表,找不到类 ExpressionVisitor

android - 如何制作一个在滑动/翻动 View 之间翻转的 Android View

java - 不会说英语以外的语言

c++ - WIn64 内存映射文件和锁定页面

java - 尝试通过 gradle 将 zip 文件上传到本地 Artifact

android - 如何在不使用 Eclipse 的情况下使用 PhoneGap 和 HTML Editor 创建一个简单的应用程序?

c++ - 如何检查内存是否已在 visual studio C++ 中释放?