我已经看过几乎所有关于凌空和泄漏,处理程序和泄漏,弱引用的堆栈溢出线程,并且几乎陷入了精神瘫痪。我一直在努力将文章中的技术翻译成我的代码。
我本质上是在尝试使用android volley get请求来“ ping”本地片段中的本地服务器,以查看其是否存在。如果是,则加载页面,如果不是,则加载空白页面,并保持“等待连接”微调器向上。
我的问题是,反复打排球会导致大量泄漏。我希望对解决这些问题具有实际经验的人能有所帮助。我确实要求答案在我发布的代码的上下文中。如果这些文章对我来说有意义,我就不会在这里发布。
这里只是我读过的几篇著名文章,但我可能在博客和堆栈溢出中读了100多篇,试图理解这个问题。
Activity leak while using volley listeners
https://www.smashingmagazine.com/2017/03/simplify-android-networking-volley-http-library/
http://blog.nimbledroid.com/2016/09/06/stop-memory-leaks.html
如果不调用isOnline(),我可以摆脱泄漏,但是很明显,程序不再满足我的需要,所以我知道泄漏与凌空或处理程序有关。 / p>
公共类DeviceFragment扩展了片段{
Handler handler;
boolean online;
boolean online_prev;
WebView webView;
private static final String TAG = "DeviceFragment";
ProgressBar spinner;
TextView spinnertext;
int toastCount;
boolean onlineBoolean;
boolean isDestroyed;
RequestQueue queue;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_device, container, false);
queue = Volley.newRequestQueue(getActivity()); // moved to help with leaks
spinner = view.findViewById(R.id.progressBar1);
spinnertext = view.findViewById(R.id.progressBar1text);
online = false;
online_prev = false;
toastCount = 1;
handler = new Handler();
isDestroyed = false;
spinner.setVisibility(View.VISIBLE);
spinnertext.setVisibility(View.VISIBLE);
webView = view.findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new myWebClient() {
@Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
view.loadUrl("about:blank");
Toast.makeText(getActivity().getApplicationContext(), "Waiting For Connection", Toast.LENGTH_LONG).show();
}
});
// New method to get to WiFi settings menu
Button wifisettings = view.findViewById(R.id.WiFiSettings);
wifisettings.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(android.provider.Settings.ACTION_WIFI_SETTINGS));
}
});
Button connect = view.findViewById(R.id.connect);
connect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
webView.loadUrl("http://10.123.40.2");
}
});
handler.postDelayed(runnableCode, 1000);
return view;
}
@Override
public void onResume() {
super.onResume();
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
@Override
public void onPause() {
super.onPause();
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
private Runnable runnableCode = new Runnable() {
@Override
public void run() {
online = onlineBoolean;
if(isDestroyed == false){
isOnline();
}
if (online == true && online_prev == false) {
webView.loadUrl("http://10.123.40.2");
spinner.setVisibility(View.GONE);
spinnertext.setVisibility(View.GONE);
toastCount = 0;
} else if (online == true && online_prev == true) {
// do nothing
} else if (online == false && online_prev == true) {
// do nothing
} else {
webView.loadUrl("about:blank");
spinner.setVisibility(View.VISIBLE);
spinnertext.setVisibility(View.VISIBLE);
if (toastCount == 0) {
Toast.makeText(getActivity().getApplicationContext(), "Wi-Fi Connection Lost - Please Check Wi-Fi Settings", Toast.LENGTH_LONG).show();
toastCount = 1;
}
}
online_prev = online;
//handler = new Handler(); // leaks?
handler.removeCallbacksAndMessages(null); // Not sure if this helps with leaks?
handler.postDelayed(this, 5000);
}
};
public class myWebClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
public void isOnline() {
//RequestQueue queue = Volley.newRequestQueue(getActivity()); // Causes huge leak. Move to public
String url = "http://10.123.40.2";
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
onlineBoolean = true;
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
onlineBoolean = false;
}
});
queue.add(stringRequest);
}
public void onDestroy () {
handler.removeCallbacks(runnableCode);
isDestroyed = true;
super.onDestroy ();
}
}
更新: 我已经实现了对处理程序和可运行程序的弱引用,而这些似乎并没有改善。
公共类DeviceFragment扩展了片段{
private final NimbleHandler nimblehander = new NimbleHandler(this);
private static class NimbleHandler extends Handler{
private WeakReference<DeviceFragment> weakReference;
public NimbleHandler(DeviceFragment activity) {
weakReference = new WeakReference<>(activity);
}
@Override public void handleMessage(Message message){
super.handleMessage(message);
}
}
private static class NimbleRunnable implements Runnable {
private WeakReference<DeviceFragment> weakReference;
public NimbleRunnable(DeviceFragment activity) {
weakReference = new WeakReference<>(activity);
}
@Override public void run(){
while(true);
}
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_device, container, false);
queue = Volley.newRequestQueue(getActivity());
spinner = view.findViewById(R.id.progressBar1);
spinnertext = view.findViewById(R.id.progressBar1text);
online = false;
online_prev = false;
toastCount = 1;
isDestroyed = false;
spinner.setVisibility(View.VISIBLE);
spinnertext.setVisibility(View.VISIBLE);
webView = view.findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new myWebClient() {
@Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
view.loadUrl("about:blank");
Toast.makeText(getActivity().getApplicationContext(), "Waiting For Connection", Toast.LENGTH_LONG).show();
}
});
nimblehander.post(runnableCode);
return view;
}
private final Runnable runnableCode = new NimbleRunnable(this) {
@Override
public void run() {
online = onlineBoolean;
if(isDestroyed == false){
isOnline();
}
// omitted rest of code to keep short
nimblehander.postDelayed(this, 5000);
}
};
}