修复DialogFragment 销毁时不能被Aria移除的问题

This commit is contained in:
AriaLyy
2017-08-08 13:40:40 +08:00
parent 506e65a73e
commit 2febe641a7
9 changed files with 232 additions and 21 deletions

View File

@@ -24,6 +24,7 @@ import android.app.Service;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.util.Log;
@@ -32,6 +33,7 @@ import com.arialyy.aria.core.common.QueueMod;
import com.arialyy.aria.core.download.DownloadReceiver;
import com.arialyy.aria.core.command.ICmd;
import com.arialyy.aria.core.inf.IReceiver;
import com.arialyy.aria.core.scheduler.AbsSchedulerListener;
import com.arialyy.aria.core.upload.UploadReceiver;
import com.arialyy.aria.orm.DbUtil;
import com.arialyy.aria.util.CommonUtil;
@@ -185,11 +187,16 @@ import org.xml.sax.SAXException;
private IReceiver putReceiver(boolean isDownload, Object obj) {
final String key = getKey(isDownload, obj);
IReceiver receiver = mReceivers.get(key);
boolean needRmReceiver = false;
final WidgetLiftManager widgetLiftManager = new WidgetLiftManager();
if (obj instanceof Dialog) {
widgetLiftManager.handleDialogLift((Dialog) obj);
needRmReceiver = widgetLiftManager.handleDialogLift((Dialog) obj);
} else if (obj instanceof PopupWindow) {
widgetLiftManager.handlePopupWindowLift((PopupWindow) obj);
needRmReceiver = widgetLiftManager.handlePopupWindowLift((PopupWindow) obj);
} else if (obj instanceof DialogFragment) {
needRmReceiver = widgetLiftManager.handleDialogFragmentLift((DialogFragment) obj);
} else if (obj instanceof android.app.DialogFragment) {
needRmReceiver = widgetLiftManager.handleDialogFragmentLift((android.app.DialogFragment) obj);
}
if (receiver == null) {
@@ -197,12 +204,14 @@ import org.xml.sax.SAXException;
DownloadReceiver dReceiver = new DownloadReceiver();
dReceiver.targetName = obj.getClass().getName();
dReceiver.obj = obj;
dReceiver.needRmReceiver = needRmReceiver;
mReceivers.put(key, dReceiver);
receiver = dReceiver;
} else {
UploadReceiver uReceiver = new UploadReceiver();
uReceiver.targetName = obj.getClass().getName();
uReceiver.obj = obj;
uReceiver.needRmReceiver = needRmReceiver;
mReceivers.put(key, uReceiver);
receiver = uReceiver;
}
@@ -217,7 +226,11 @@ import org.xml.sax.SAXException;
String clsName = obj.getClass().getName();
String key = "";
if (!(obj instanceof Activity)) {
if (obj instanceof android.support.v4.app.Fragment) {
if (obj instanceof DialogFragment) {
key = clsName + "_" + ((DialogFragment) obj).getActivity().getClass().getName();
} else if (obj instanceof android.app.DialogFragment) {
key = clsName + "_" + ((android.app.DialogFragment) obj).getActivity().getClass().getName();
} else if (obj instanceof android.support.v4.app.Fragment) {
key = clsName + "_" + ((Fragment) obj).getActivity().getClass().getName();
} else if (obj instanceof android.app.Fragment) {
key = clsName + "_" + ((android.app.Fragment) obj).getActivity().getClass().getName();
@@ -314,7 +327,22 @@ import org.xml.sax.SAXException;
}
/**
* onDestroy
* 移除指定对象的receiver
*/
public void removeReceiver(Object obj) {
String clsName = obj.getClass().getName();
for (Iterator<Map.Entry<String, IReceiver>> iter = mReceivers.entrySet().iterator();
iter.hasNext(); ) {
Map.Entry<String, IReceiver> entry = iter.next();
String key = entry.getKey();
if (key.contains(clsName)) {
iter.remove();
}
}
}
/**
* Aria注册对象被销毁时调用
*/
void destroySchedulerListener(Object obj) {
String clsName = obj.getClass().getName();
@@ -324,9 +352,11 @@ import org.xml.sax.SAXException;
String key = entry.getKey();
if (key.contains(clsName)) {
IReceiver receiver = mReceivers.get(key);
receiver.removeSchedulerListener();
receiver.unRegister();
receiver.destroy();
if (receiver != null) {
receiver.removeSchedulerListener();
receiver.unRegister();
receiver.destroy();
}
iter.remove();
}
}

View File

@@ -15,9 +15,12 @@
*/
package com.arialyy.aria.core;
import android.annotation.TargetApi;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Build;
import android.os.Message;
import android.support.v4.app.DialogFragment;
import android.util.Log;
import android.widget.PopupWindow;
import com.arialyy.aria.util.CommonUtil;
@@ -30,23 +33,45 @@ import java.lang.reflect.Field;
final class WidgetLiftManager {
private final String TAG = "WidgetLiftManager";
/**
* 处理DialogFragment事件
*
* @param dialogFragment {@link android.app.DialogFragment}
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB) boolean handleDialogFragmentLift(
android.app.DialogFragment dialogFragment) {
return handleDialogLift(dialogFragment.getDialog());
}
/**
* 处理DialogFragment事件
*
* @param dialogFragment {@link android.support.v4.app.DialogFragment}
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB) boolean handleDialogFragmentLift(
DialogFragment dialogFragment) {
return handleDialogLift(dialogFragment.getDialog());
}
/**
* 处理悬浮框取消或dismiss事件
*/
void handlePopupWindowLift(PopupWindow popupWindow) {
boolean handlePopupWindowLift(PopupWindow popupWindow) {
try {
Field dismissField = CommonUtil.getField(popupWindow.getClass(), "mOnDismissListener");
PopupWindow.OnDismissListener listener =
(PopupWindow.OnDismissListener) dismissField.get(popupWindow);
if (listener != null) {
Log.e(TAG, "你已经对PopupWindow设置了Dismiss事件。为了防止内存泄露"
+ "请在dismiss方法中调用Aria.download(this).removeSchedulerListener();来注销事件");
+ "请在dismiss方法中调用Aria.download(this).unRegister();来注销事件");
return true;
} else {
popupWindow.setOnDismissListener(createPopupWindowListener(popupWindow));
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return false;
}
/**
@@ -63,7 +88,7 @@ final class WidgetLiftManager {
/**
* 处理对话框取消或dismiss
*/
void handleDialogLift(Dialog dialog) {
boolean handleDialogLift(Dialog dialog) {
try {
Field dismissField = CommonUtil.getField(dialog.getClass(), "mDismissMessage");
Message dismissMsg = (Message) dismissField.get(dialog);
@@ -72,8 +97,10 @@ final class WidgetLiftManager {
Field cancelField = CommonUtil.getField(dialog.getClass(), "mCancelMessage");
Message cancelMsg = (Message) cancelField.get(dialog);
if (cancelMsg != null) {
Log.e(TAG, "你已经对Dialog设置了Dismiss和cancel事件。为了防止内存泄露,"
+ "请在dismiss方法中调用Aria.download(this).removeSchedulerListener();来注销事件");
Log.e(TAG, "你已经对Dialog设置了Dismiss和cancel事件。"
+ "为了防止内存泄露,请在dismiss方法中调用Aria.download(this).unRegister();来注销事件\n"
+ "如果你使用的是DialogFragment那么你需要在onDestroy()中进行销毁Aria事件操作");
return true;
} else {
dialog.setOnCancelListener(createCancelListener());
}
@@ -83,6 +110,7 @@ final class WidgetLiftManager {
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return false;
}
/**

View File

@@ -16,6 +16,7 @@
package com.arialyy.aria.core.download;
import android.support.annotation.NonNull;
import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.inf.AbsEntity;
import com.arialyy.aria.core.inf.AbsReceiver;
@@ -128,6 +129,9 @@ public class DownloadReceiver extends AbsReceiver {
if (dgCounter != null && dgCounter.contains(className)) {
DownloadGroupSchedulers.getInstance().unRegister(obj);
}
if (needRmReceiver) {
AriaManager.getInstance(AriaManager.APP).removeReceiver(obj);
}
}
/**
@@ -163,8 +167,7 @@ public class DownloadReceiver extends AbsReceiver {
*/
public DownloadEntity getDownloadEntity(String downloadUrl) {
CheckUtil.checkDownloadUrl(downloadUrl);
return DbEntity.findFirst(DownloadEntity.class, "url=? and isGroupChild='false'",
downloadUrl);
return DbEntity.findFirst(DownloadEntity.class, "url=? and isGroupChild='false'", downloadUrl);
}
/**

View File

@@ -20,8 +20,11 @@ package com.arialyy.aria.core.inf;
* Created by AriaL on 2017/6/27.
*/
public abstract class AbsReceiver<ENTITY extends AbsEntity> implements IReceiver<ENTITY>{
public abstract class AbsReceiver<ENTITY extends AbsEntity> implements IReceiver<ENTITY> {
public String targetName;
public Object obj;
/**
* 当dialog、dialogFragment、popupwindow已经被设置了关闭监听时需要手动移除receiver
*/
public boolean needRmReceiver = false;
}

View File

@@ -146,5 +146,8 @@ public class UploadReceiver extends AbsReceiver<UploadEntity> {
if (dCounter != null && dCounter.contains(className)) {
UploadSchedulers.getInstance().unRegister(obj);
}
if (needRmReceiver) {
AriaManager.getInstance(AriaManager.APP).removeReceiver(obj);
}
}
}