[英]Fix activity leak when listener keeps implicit reference
在MessageFeedActivity onCreate方法中,它通过调用CTFeedAPI class 的getMessageTypes方法加载提要。
public class MessageFeedActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Setting the listener
CTFeedAPI ctFeedAPI = new CTFeedAPI(new CTFeedAPI.CTFeedAPIListener() {
@Override
public void feedAPISuccessListener(Object object) {
// Handle Success
}
@Override
public void feedAPIErrorListener(int error) {
// Handle Error
}
});
ctFeedAPI.getMessageTypes();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
并等待CTFeedAPIListener响应。 和CTFeedAPI class make.network 请求通过调用NetworkRequest class 的performRequest方法作为
public class CTFeedAPI implements NetworkListener {
private CTFeedAPIListener apiListener;
public CTFeedAPI(CTFeedAPIListener feedAPIListener) {
apiListener = feedAPIListener;
}
public void getMessageTypes() {
Map < String, String > params = new HashMap < > ();
params.put("f", "GetMessageTypes");
NetworkRequest networkRequest = new NetworkRequest(this);
networkRequest.performRequest();
}
public interface CTFeedAPIListener {
void feedAPISuccessListener(Object object);
void feedAPIErrorListener(int error);
}
}
并等待NetworkListener响应
public class NetworkRequest {
private NetworkListener mListener;
public interface NetworkListener {
void networkReqSuccessListener(String cacheKey, String tag, String response);
void networkReqErrorListener(String tag, int error);
}
public NetworkRequest(NetworkListener listener) {
this.mListener = listener;
}
public void performRequest(
// Perform Network Requests and respond as
if (mListener != null) {
if (success) {
mListener.networkReqSuccessListener(getUrl(), getTag(), response);
} else {
mListener.networkReqErrorListener(getTag(), err_msg);
}
}
}
当用户按下返回键时,在销毁 MessageFeedActivity 之前,系统调用 'onDestroy' 方法。 不幸的是,由于后台线程(NetworkRequest 类中的 performRequest 方法)仍然保留对它的引用,因此发生了泄漏。
那么如何在 MessageFeedActivity 中实现CTFeedAPIListener引用来消除泄漏。
在这种设计中,您不仅会泄漏 memory,而且您的代码也会高度耦合并且很难测试; 容易出现难以检测的错误。 我建议您实施 MVP 或类似架构。 你的活动不应该知道任何关于你的网络层的信息。 添加一个表示层,负责代表您的活动请求某些内容,并使用界面更新您的活动。 您的演示者应该访问从存储库层的响应映射的业务实体,该实体负责.network 或 Db 访问并将值返回给客户端演示者。 这样,您的演示者和业务逻辑层将解耦并且易于独立测试。 将来如果业务需求发生变化,您的更改不会影响其他层。 有关该主题的更多信息,请参阅本文。
弱引用对象,不阻止其引用对象可终结、终结,然后回收。 弱引用最常用于实现规范化映射。
假设垃圾收集器在某个时间点确定 object 是弱可达的。 届时,它将自动清除对 object 的所有弱引用,以及对任何其他弱可达对象的所有弱引用,而 object 可通过强引用链和软引用链从中访问。 同时,它会声明所有以前的弱可达对象是可终结的。 同时或在稍后的某个时间,它会将那些在引用队列中注册的新清除的弱引用排入队列。
您可以使用弱引用:
import java.lang.ref.WeakReference;
public class NetworkRequest {
public interface NetworkListener {
void networkReqSuccessListener(String cacheKey, String tag, String response);
void networkReqErrorListener(String tag, int error);
}
private WeakReference<NetworkListener> mListener;
public NetworkRequest(NetworkListener listener) {
this.mListener = new WeakReference<NetworkListener>(listener);
}
public void performRequest(){
// Perform Network Requests and respond as
NetworkListener listener = mListener.get();
if (listener != null) {
if (success) listener.networkReqSuccessListener(getUrl(), getTag(), response);
else listener.networkReqErrorListener(getTag(), err_msg);
}
}
}
public class CTFeedAPI implements NetworkListener {
private WeakReference<CTFeedAPIListener> apiListener;
public CTFeedAPI(CTFeedAPIListener feedAPIListener) {
apiListener = new WeakReference<>(feedAPIListener);
}
public void getMessageTypes() {
Map < String, String > params = new HashMap < > ();
params.put("f", "GetMessageTypes");
NetworkRequest networkRequest = new NetworkRequest(this);
networkRequest.performRequest();
}
public interface CTFeedAPIListener {
void feedAPISuccessListener(Object object);
void feedAPIErrorListener(int error);
}
}
将CTFeedAPI
和CTFeedAPIListener
保存为MessageFeedActivity
的实例变量,以防止GC
在出现活动时收集它们:
public class MessageFeedActivity extends AppCompatActivity {
private CTFeedAPI ctFeedAPI = null;// keeping a reference to CTFeedAPI
private CTFeedAPIListener listener = null;// keeping a reference to listener
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Setting the listener
listener = new CTFeedAPI.CTFeedAPIListener() {
@Override
public void feedAPISuccessListener(Object object) {
// Handle Success
}
@Override
public void feedAPIErrorListener(int error) {
// Handle Error
}
});
ctFeedAPI = new CTFeedAPI(listener);
ctFeedAPI.getMessageTypes();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.