Logcat 显示 WindowLeaked
Logcat showing WindowLeaked
即使我的应用程序没有崩溃。但是 logcat 显示了这个调试日志。我想知道是什么导致了这个问题。我不太了解线程,所以这可能与线程使用不当有关。
06-12 12:37:37.349 12433-12433/com.ets.medecord E/WindowManager﹕ Activity com.ets.medecord.LoginActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@405403d0 that was originally added here
android.view.WindowLeaked: Activity com.ets.medecord.LoginActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@405403d0 that was originally added here
at android.view.ViewRoot.<init>(ViewRoot.java:259)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
at android.view.Window$LocalWindowManager.addView(Window.java:465)
at android.app.Dialog.show(Dialog.java:241)
at com.ets.medecord.LoginActivity.attemptLogin(LoginActivity.java:125)
at com.ets.medecord.LoginActivity.access0(LoginActivity.java:45)
at com.ets.medecord.LoginActivity.onClick(LoginActivity.java:87)
at android.view.View.performClick(View.java:2506)
at android.view.View$PerformClick.run(View.java:9112)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3835)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:864)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:622)
at dalvik.system.NativeStart.main(Native Method)
这是我正在使用的代码,看看是否可以。
在这里,我尝试在工作线程完成其工作后关闭对话框。
final String user_email = email;
final String user_password = password;
Log.d(TAG, "email:" + email);
Log.d(TAG, "password:" + password);
pDialog = new ProgressDialog(this);
pDialog.setMessage("Loading....");
pDialog.show();
new Thread(new Runnable() {
@Override
public void run() {
HttpClient httpClient = new DefaultHttpClient();
HttpResponse httpResponse = null;
HttpPost httpPost = new HttpPost("http://elitetotality.com/medicord/");
List<NameValuePair> nameValuePair = new ArrayList<>();
nameValuePair.add(new BasicNameValuePair("tag", "login"));
nameValuePair.add(new BasicNameValuePair("email", user_email));
nameValuePair.add(new BasicNameValuePair("password", user_password));
try {
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePair));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try {
httpResponse = httpClient.execute(httpPost);
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
httpResponse.getEntity().getContent(), "UTF-8"));
StringBuilder builder = new StringBuilder();
for (String line = null; (line = reader.readLine()) != null; ) {
builder.append(line).append("\n");
}
String httpResponseString = builder.toString();
strResponse = httpResponseString;
Log.d(TAG, httpResponseString);
} catch (IOException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
@Override
public void run() {
pDialog.hide();
pDialog.dismiss();
}
});
JSONObject reader;
try {
if(strResponse != null){
reader = new JSONObject(strResponse);
String error = reader.get("error").toString();
Log.d(JSON_TAG, error);
if(error.equals("false")) {
String userName = reader.getJSONObject("user").get("name").toString();
editor.putBoolean("isLoggedIn", true);
editor.putString("userName", userName);
editor.apply();
startActivity(new Intent(getApplicationContext(), RandomProfileActivity.class));
finish();
} else {
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),"Either email or password is incorrect!"
,Toast.LENGTH_SHORT).show();
}
});
}
}
} catch(JSONException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}).start();
您正试图在退出 Activity
后关闭 Dialog
。因为即使在 activity 被销毁后,您的工作线程仍将继续执行。如果您在 Activity
被销毁后尝试关闭对话框,将导致 leaked window exception
尝试将此代码添加到您的 activity。
@Override
public void onDestroy() {
super.onDestroy();
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
}
更详细的回答
更改这部分代码:
handler.post(new Runnable() {
@Override
public void run() {
pDialog.hide();
pDialog.dismiss();
}
});
至:
pDialog.dismiss();
Handler.post
在当前方法完成后的某个时间将 运行nable 代码设为 运行。这就是为什么你收到泄漏警告,你正在泄漏一个对话框。
Android 提供 AsyncTask 来进行短期异步操作。您可以使用 onPreExecute
来显示您的 Dialog
并使用 onPostExecute
来消除它。
即使我的应用程序没有崩溃。但是 logcat 显示了这个调试日志。我想知道是什么导致了这个问题。我不太了解线程,所以这可能与线程使用不当有关。
06-12 12:37:37.349 12433-12433/com.ets.medecord E/WindowManager﹕ Activity com.ets.medecord.LoginActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@405403d0 that was originally added here
android.view.WindowLeaked: Activity com.ets.medecord.LoginActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@405403d0 that was originally added here
at android.view.ViewRoot.<init>(ViewRoot.java:259)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
at android.view.Window$LocalWindowManager.addView(Window.java:465)
at android.app.Dialog.show(Dialog.java:241)
at com.ets.medecord.LoginActivity.attemptLogin(LoginActivity.java:125)
at com.ets.medecord.LoginActivity.access0(LoginActivity.java:45)
at com.ets.medecord.LoginActivity.onClick(LoginActivity.java:87)
at android.view.View.performClick(View.java:2506)
at android.view.View$PerformClick.run(View.java:9112)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3835)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:864)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:622)
at dalvik.system.NativeStart.main(Native Method)
这是我正在使用的代码,看看是否可以。 在这里,我尝试在工作线程完成其工作后关闭对话框。
final String user_email = email;
final String user_password = password;
Log.d(TAG, "email:" + email);
Log.d(TAG, "password:" + password);
pDialog = new ProgressDialog(this);
pDialog.setMessage("Loading....");
pDialog.show();
new Thread(new Runnable() {
@Override
public void run() {
HttpClient httpClient = new DefaultHttpClient();
HttpResponse httpResponse = null;
HttpPost httpPost = new HttpPost("http://elitetotality.com/medicord/");
List<NameValuePair> nameValuePair = new ArrayList<>();
nameValuePair.add(new BasicNameValuePair("tag", "login"));
nameValuePair.add(new BasicNameValuePair("email", user_email));
nameValuePair.add(new BasicNameValuePair("password", user_password));
try {
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePair));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try {
httpResponse = httpClient.execute(httpPost);
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
httpResponse.getEntity().getContent(), "UTF-8"));
StringBuilder builder = new StringBuilder();
for (String line = null; (line = reader.readLine()) != null; ) {
builder.append(line).append("\n");
}
String httpResponseString = builder.toString();
strResponse = httpResponseString;
Log.d(TAG, httpResponseString);
} catch (IOException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
@Override
public void run() {
pDialog.hide();
pDialog.dismiss();
}
});
JSONObject reader;
try {
if(strResponse != null){
reader = new JSONObject(strResponse);
String error = reader.get("error").toString();
Log.d(JSON_TAG, error);
if(error.equals("false")) {
String userName = reader.getJSONObject("user").get("name").toString();
editor.putBoolean("isLoggedIn", true);
editor.putString("userName", userName);
editor.apply();
startActivity(new Intent(getApplicationContext(), RandomProfileActivity.class));
finish();
} else {
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(),"Either email or password is incorrect!"
,Toast.LENGTH_SHORT).show();
}
});
}
}
} catch(JSONException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}).start();
您正试图在退出 Activity
后关闭 Dialog
。因为即使在 activity 被销毁后,您的工作线程仍将继续执行。如果您在 Activity
被销毁后尝试关闭对话框,将导致 leaked window exception
尝试将此代码添加到您的 activity。
@Override
public void onDestroy() {
super.onDestroy();
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
}
更详细的回答
更改这部分代码:
handler.post(new Runnable() {
@Override
public void run() {
pDialog.hide();
pDialog.dismiss();
}
});
至:
pDialog.dismiss();
Handler.post
在当前方法完成后的某个时间将 运行nable 代码设为 运行。这就是为什么你收到泄漏警告,你正在泄漏一个对话框。
Android 提供 AsyncTask 来进行短期异步操作。您可以使用 onPreExecute
来显示您的 Dialog
并使用 onPostExecute
来消除它。