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

pull/330/head
AriaLyy 7 years ago
parent 506e65a73e
commit 2febe641a7
  1. 38
      Aria/src/main/java/com/arialyy/aria/core/AriaManager.java
  2. 38
      Aria/src/main/java/com/arialyy/aria/core/WidgetLiftManager.java
  3. 7
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java
  4. 5
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsReceiver.java
  5. 3
      Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java
  6. 2
      app/src/main/java/com/arialyy/simple/download/DownloadActivity.java
  7. 7
      app/src/main/java/com/arialyy/simple/download/DownloadDialog.java
  8. 112
      app/src/main/java/com/arialyy/simple/download/DownloadDialogFragment.java
  9. 33
      app/src/main/res/layout/dialog_fragment_download.xml

@ -24,6 +24,7 @@ import android.app.Service;
import android.content.Context; import android.content.Context;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; 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.download.DownloadReceiver;
import com.arialyy.aria.core.command.ICmd; import com.arialyy.aria.core.command.ICmd;
import com.arialyy.aria.core.inf.IReceiver; 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.core.upload.UploadReceiver;
import com.arialyy.aria.orm.DbUtil; import com.arialyy.aria.orm.DbUtil;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
@ -185,11 +187,16 @@ import org.xml.sax.SAXException;
private IReceiver putReceiver(boolean isDownload, Object obj) { private IReceiver putReceiver(boolean isDownload, Object obj) {
final String key = getKey(isDownload, obj); final String key = getKey(isDownload, obj);
IReceiver receiver = mReceivers.get(key); IReceiver receiver = mReceivers.get(key);
boolean needRmReceiver = false;
final WidgetLiftManager widgetLiftManager = new WidgetLiftManager(); final WidgetLiftManager widgetLiftManager = new WidgetLiftManager();
if (obj instanceof Dialog) { if (obj instanceof Dialog) {
widgetLiftManager.handleDialogLift((Dialog) obj); needRmReceiver = widgetLiftManager.handleDialogLift((Dialog) obj);
} else if (obj instanceof PopupWindow) { } 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) { if (receiver == null) {
@ -197,12 +204,14 @@ import org.xml.sax.SAXException;
DownloadReceiver dReceiver = new DownloadReceiver(); DownloadReceiver dReceiver = new DownloadReceiver();
dReceiver.targetName = obj.getClass().getName(); dReceiver.targetName = obj.getClass().getName();
dReceiver.obj = obj; dReceiver.obj = obj;
dReceiver.needRmReceiver = needRmReceiver;
mReceivers.put(key, dReceiver); mReceivers.put(key, dReceiver);
receiver = dReceiver; receiver = dReceiver;
} else { } else {
UploadReceiver uReceiver = new UploadReceiver(); UploadReceiver uReceiver = new UploadReceiver();
uReceiver.targetName = obj.getClass().getName(); uReceiver.targetName = obj.getClass().getName();
uReceiver.obj = obj; uReceiver.obj = obj;
uReceiver.needRmReceiver = needRmReceiver;
mReceivers.put(key, uReceiver); mReceivers.put(key, uReceiver);
receiver = uReceiver; receiver = uReceiver;
} }
@ -217,7 +226,11 @@ import org.xml.sax.SAXException;
String clsName = obj.getClass().getName(); String clsName = obj.getClass().getName();
String key = ""; String key = "";
if (!(obj instanceof Activity)) { 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(); key = clsName + "_" + ((Fragment) obj).getActivity().getClass().getName();
} else if (obj instanceof android.app.Fragment) { } else if (obj instanceof android.app.Fragment) {
key = clsName + "_" + ((android.app.Fragment) obj).getActivity().getClass().getName(); 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) { void destroySchedulerListener(Object obj) {
String clsName = obj.getClass().getName(); String clsName = obj.getClass().getName();
@ -324,9 +352,11 @@ import org.xml.sax.SAXException;
String key = entry.getKey(); String key = entry.getKey();
if (key.contains(clsName)) { if (key.contains(clsName)) {
IReceiver receiver = mReceivers.get(key); IReceiver receiver = mReceivers.get(key);
if (receiver != null) {
receiver.removeSchedulerListener(); receiver.removeSchedulerListener();
receiver.unRegister(); receiver.unRegister();
receiver.destroy(); receiver.destroy();
}
iter.remove(); iter.remove();
} }
} }

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

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

@ -23,5 +23,8 @@ package com.arialyy.aria.core.inf;
public abstract class AbsReceiver<ENTITY extends AbsEntity> implements IReceiver<ENTITY> { public abstract class AbsReceiver<ENTITY extends AbsEntity> implements IReceiver<ENTITY> {
public String targetName; public String targetName;
public Object obj; public Object obj;
/**
* 当dialogdialogFragmentpopupwindow已经被设置了关闭监听时需要手动移除receiver
*/
public boolean needRmReceiver = false;
} }

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

@ -98,6 +98,8 @@ public class DownloadActivity extends BaseActivity<ActivityDownloadMeanBinding>
case R.id.dialog_task: case R.id.dialog_task:
DownloadDialog dialog = new DownloadDialog(this); DownloadDialog dialog = new DownloadDialog(this);
dialog.show(); dialog.show();
//DownloadDialogFragment dialog = new DownloadDialogFragment(this);
//dialog.show(getSupportFragmentManager(), "dialog");
break; break;
case R.id.pop_task: case R.id.pop_task:
DownloadPopupWindow pop = new DownloadPopupWindow(this); DownloadPopupWindow pop = new DownloadPopupWindow(this);

@ -57,15 +57,12 @@ public class DownloadDialog extends AbsDialog {
} }
private void init() { private void init() {
if (Aria.download(this).taskExists(DOWNLOAD_URL)) {
DownloadTarget target = Aria.download(this).load(DOWNLOAD_URL);
int p = (int) (target.getCurrentProgress() * 100 / target.getFileSize());
mPb.setProgress(p);
}
Aria.download(this).register(); Aria.download(this).register();
DownloadEntity entity = Aria.download(this).getDownloadEntity(DOWNLOAD_URL); DownloadEntity entity = Aria.download(this).getDownloadEntity(DOWNLOAD_URL);
if (entity != null) { if (entity != null) {
mSize.setText(CommonUtil.formatFileSize(entity.getFileSize())); mSize.setText(CommonUtil.formatFileSize(entity.getFileSize()));
int p = (int) (entity.getCurrentProgress() * 100 / entity.getFileSize());
mPb.setProgress(p);
int state = entity.getState(); int state = entity.getState();
setBtState(state != DownloadEntity.STATE_RUNNING); setBtState(state != DownloadEntity.STATE_RUNNING);
} else { } else {

@ -0,0 +1,112 @@
package com.arialyy.simple.download;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Toast;
import butterknife.OnClick;
import com.arialyy.annotations.Download;
import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.frame.util.show.T;
import com.arialyy.simple.R;
import com.arialyy.simple.base.BaseDialog;
import com.arialyy.simple.databinding.DialogFragmentDownloadBinding;
/**
* Created by Aria.Lao on 2017/8/8.
*/
@SuppressLint("ValidFragment") public class DownloadDialogFragment
extends BaseDialog<DialogFragmentDownloadBinding> {
private static final String DOWNLOAD_URL =
"http://res3.d.cn/android/new/game/2/78702/fzjh_1499390260312.apk?f=web_1";
protected DownloadDialogFragment(Object obj) {
super(obj);
}
@Override protected void init(Bundle savedInstanceState) {
super.init(savedInstanceState);
Aria.download(this).register();
DownloadEntity entity = Aria.download(this).getDownloadEntity(DOWNLOAD_URL);
if (entity != null) {
getBinding().setFileSize(CommonUtil.formatFileSize(entity.getFileSize()));
getBinding().setProgress((int) (entity.getCurrentProgress() * 100 / entity.getFileSize()));
}
}
@Override protected int setLayoutId() {
return R.layout.dialog_fragment_download;
}
@Override public void onDestroy() {
super.onDestroy();
Aria.download(this).unRegister();
}
@Download.onPre(DOWNLOAD_URL) protected void onPre(DownloadTask task) {
}
@Download.onTaskStart(DOWNLOAD_URL) void taskStart(DownloadTask task) {
getBinding().setFileSize(task.getConvertFileSize());
}
@Download.onTaskRunning(DOWNLOAD_URL) protected void running(DownloadTask task) {
long len = task.getFileSize();
if (len == 0) {
getBinding().setProgress(0);
} else {
getBinding().setProgress(task.getPercent());
}
getBinding().setSpeed(task.getConvertSpeed());
}
@Download.onTaskResume(DOWNLOAD_URL) void taskResume(DownloadTask task) {
}
@Download.onTaskStop(DOWNLOAD_URL) void taskStop(DownloadTask task) {
getBinding().setSpeed("");
}
@Download.onTaskCancel(DOWNLOAD_URL) void taskCancel(DownloadTask task) {
getBinding().setProgress(0);
Toast.makeText(getContext(), "取消下载", Toast.LENGTH_SHORT).show();
getBinding().setSpeed("");
}
@Download.onTaskFail(DOWNLOAD_URL) void taskFail(DownloadTask task) {
Toast.makeText(getContext(), "下载失败", Toast.LENGTH_SHORT).show();
}
@Download.onTaskComplete(DOWNLOAD_URL) void taskComplete(DownloadTask task) {
getBinding().setProgress(100);
Toast.makeText(getContext(), "下载完成", Toast.LENGTH_SHORT).show();
getBinding().setSpeed("");
}
@Download.onNoSupportBreakPoint(DOWNLOAD_URL)
public void onNoSupportBreakPoint(DownloadTask task) {
T.showShort(getContext(), "该下载链接不支持断点");
}
@OnClick({ R.id.start, R.id.stop, R.id.cancel }) public void onClick(View view) {
switch (view.getId()) {
case R.id.start:
Aria.download(this)
.load(DOWNLOAD_URL)
.setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/放置江湖.apk")
.start();
break;
case R.id.stop:
Aria.download(this).load(DOWNLOAD_URL).stop();
break;
case R.id.cancel:
Aria.download(this).load(DOWNLOAD_URL).cancel();
break;
}
}
}

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto"
>
<data>
<variable
name="fileSize"
type="String"
/>
<variable
name="speed"
type="String"
/>
<variable
name="progress"
type="int"
/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<include
layout="@layout/content_single"
bind:fileSize="@{fileSize}"
bind:progress="@{progress}"
bind:speed="@{speed}"
/>
</LinearLayout>
</layout>
Loading…
Cancel
Save