当进度对话框可见时按下主页按钮时出现以下异常。我已经浏览了很多SO帖子,但他们只为活动屏幕提供了解决方案。在这种情况下,我在非活动屏幕中获取此异常,即在我的数组适配器中。
例外:
android.view.WindowLeaked: Activity com.meru.parryvaibhav.MrpActivity has leaked window com.android.internal.policy.PhoneWindow$DecorView{78d89f9 V.E...... R......D 0,0-480,174} that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:460)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:306)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
at android.app.Dialog.show(Dialog.java:326)
at com.android.andy.ResourceArrayAdapter$DownloadFileTask.onProgressUpdate(ResourceArrayAdapter.java:297)
at com.android.andy.ResourceArrayAdapter$DownloadFileTask.onProgressUpdate(ResourceArrayAdapter.java:192)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:671)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:5728)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)
适配器代码:
package com.android.andy;
import java.util.ArrayList;
import java.util.List;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.view.LayoutInflater;
import android.widget.TextView;
import android.widget.Button;
import android.os.AsyncTask;
import android.content.Intent;
import java.net.*;
import java.io.BufferedInputStream;
import android.net.Uri;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.widget.Toast;
import android.os.Environment;;
import android.view.View.OnClickListener;
import android.content.SharedPreferences;
import android.app.ProgressDialog;
import android.webkit.MimeTypeMap;
public class ResourceArrayAdapter extends ArrayAdapter<ResourceElement>
{
private List<ResourceElement> messages = new ArrayList<ResourceElement>();
LayoutInflater inflater;
Uri uri=null;
private SharedPreferences userPrefer;
@Override
public void add(ResourceElement object)
{
messages.add(object);
super.add(object);
}
public void addAll(List<ResourceElement> list)
{
messages.addAll(list);
//super.addAll(list);
}
public void clear()
{
messages.clear();
//super.addAll(list);
}
@Override
public void remove(ResourceElement object)
{
messages.remove(object);
super.remove(object);
}
private static class ViewHolder
{
TextView sno;
TextView description;
Button view_pdf;
//TableLayout table;
}
public ResourceArrayAdapter(Context context, int textViewResourceId)
{
super(context, textViewResourceId);
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
userPrefer = context.getSharedPreferences(Props.USERPREFERENCES, Context.MODE_PRIVATE);
}
public int getCount()
{
return this.messages.size();
}
public ResourceElement getItem(int index)
{
return this.messages.get(index);
}
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
if (convertView == null)
{
convertView = inflater.inflate(R.layout.resource_element, parent, false);
holder = new ViewHolder();
holder.sno = (TextView) convertView.findViewById(R.id.sno);
//holder.table = (TableLayout) convertView.findViewById(R.id.table_layout);
holder.description = (TextView) convertView.findViewById(R.id.description);
holder.view_pdf = (Button) convertView.findViewById(R.id.view_pdf);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.view_pdf.setOnClickListener(new OnClickListener()
{
public void onClick(View view)
{
new DownloadFileTask(reportPath,sno,size).execute();
}
});
return convertView;
}
private class DownloadFileTask extends AsyncTask<String, String, String>
{
private ProgressDialog vDialog;
private String webpath,sno,size;String filename,filepath;String response="false";
public DownloadFileTask(String wpath,String ser_no,String file_size)
{
sno = ser_no;
webpath = wpath;
size = file_size;
}
@Override
protected void onPreExecute()
{
super.onPreExecute();
// Get the screen's density scale
vDialog = new ProgressDialog(ResourceArrayAdapter.this.getContext());
}
@Override
protected String doInBackground(String... args)
{
publishProgress("");
StringBuilder sb = new StringBuilder(webpath.replaceFirst(".*/([^/?]+).*", "$1"));
filename = sb.toString();
InputStream inputStream=null;
FileOutputStream outputStream =null; HttpURLConnection connection = null;long fileSize =0L,freespace=0L;
try
{
URL filURL = new URL(webpath);
byte buffer[] = new byte[1024];
int dataSize;
long loadedSize = 0L;
connection =(HttpURLConnection) filURL.openConnection();
int resCode = connection.getResponseCode();
if(!(resCode == HttpURLConnection.HTTP_ACCEPTED || resCode == HttpURLConnection.HTTP_OK))
{
response = connection.getResponseMessage();
return response;
}
fileSize = connection.getContentLength();
File appdataDir = getDataFolder(ResourceArrayAdapter.this.getContext());
freespace = appdataDir.getFreeSpace();
if(fileSize > freespace)
{
response="Insufficient Storage.Free "+String.format("%.2f", (((double)(fileSize-freespace))/(1024*1024)))+" MB space.";
return response;
}
inputStream = new BufferedInputStream(filURL.openStream(), 10240);
File cacheFile = new File(appdataDir,filename);
cacheFile.createNewFile();
filepath = cacheFile.getAbsolutePath();
outputStream = new FileOutputStream(cacheFile);
while ((dataSize = inputStream.read(buffer)) != -1)
{
loadedSize += dataSize;
outputStream.write(buffer, 0, dataSize);
//publishProgress((((float)loadedSize/fileSize)));
response="true";
}
outputStream.close();
}
catch(Exception e)
{
response = e.getMessage();
e.printStackTrace();
}
finally
{
try{
if(outputStream!=null)
outputStream.close();
if(inputStream!=null)
inputStream.close();
}catch(Exception ioex){}
}
return response;
}
@Override
protected void onProgressUpdate(String... dprogress)
{
super.onProgressUpdate();
vDialog = new ProgressDialog(ResourceArrayAdapter.this.getContext());
vDialog.setMessage("Downloading "+filename+"..");
vDialog.setIndeterminate(false);
vDialog.setCancelable(false);
Log.e("vdialog: ","Showing");
try{
vDialog.show(); //getting error here
}
catch (Exception e)
{
e.printStackTrace();
}
}
@Override
protected void onPostExecute(String isdownloaded)
{
if ((vDialog != null) && vDialog.isShowing()) {
vDialog.dismiss();
}
if (isdownloaded.equals("true"))
{
try{
File localpath = new File(getDataFolder(ResourceArrayAdapter.this.getContext()),filename);
if(localpath.exists())
{
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.fromFile(localpath));
ResourceArrayAdapter.this.getContext().startActivity(intent);
}
}
catch(Exception fe)
{
}
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB)
{
new SendDownloadAck(sno,size,webpath).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else
{
new SendDownloadAck(sno,size,webpath).execute();
}
}
else
{
Toast.makeText(ResourceArrayAdapter.this.getContext(),"Download Failed.", Toast.LENGTH_SHORT).show();
}
}
}
}
This Async Task is used for downloading a PDF file which may take 30 secs upto one minute. so in that time interval if the user presses the home button i am getting this error. I need to know where to dismiss the progress dialog which runs in a adapter class.
EDIT1:
private class DownloadFileTask extends AsyncTask<String, String, String>
{
private ProgressDialog vDialog;
private String webpath,sno,size;String filename,filepath;String response="false";
public DownloadFileTask(String wpath,String ser_no,String file_size)
{
sno = ser_no;
webpath = wpath;
size = file_size;
}
@Override
protected void onPreExecute()
{
super.onPreExecute();
vDialog = new ProgressDialog(ResourceArrayAdapter.this.getContext());
vDialog.setMessage("Downloading "+filename+"..");
vDialog.setIndeterminate(false);
vDialog.setCancelable(false);
vDialog.show();
}
@Override
protected String doInBackground(String... args)
{
publishProgress("");
StringBuilder sb = new StringBuilder(webpath.replaceFirst(".*/([^/?]+).*", "$1"));
filename = sb.toString();
InputStream inputStream=null;
FileOutputStream outputStream =null; HttpURLConnection connection = null;long fileSize =0L,freespace=0L;
try
{
URL filURL = new URL(webpath);
byte buffer[] = new byte[1024];
int dataSize;
long loadedSize = 0L;
connection =(HttpURLConnection) filURL.openConnection();
int resCode = connection.getResponseCode();
if(!(resCode == HttpURLConnection.HTTP_ACCEPTED || resCode == HttpURLConnection.HTTP_OK))
{
response = connection.getResponseMessage();
return response;
}
fileSize = connection.getContentLength();
File appdataDir = getDataFolder(ResourceArrayAdapter.this.getContext());
freespace = appdataDir.getFreeSpace();
if(fileSize > freespace)
{
response="Insufficient Storage.Free "+String.format("%.2f", (((double)(fileSize-freespace))/(1024*1024)))+" MB space.";
return response;
}
inputStream = new BufferedInputStream(filURL.openStream(), 10240);
File cacheFile = new File(appdataDir,filename);
cacheFile.createNewFile();
filepath = cacheFile.getAbsolutePath();
outputStream = new FileOutputStream(cacheFile);
while ((dataSize = inputStream.read(buffer)) != -1)
{
loadedSize += dataSize;
outputStream.write(buffer, 0, dataSize);
//publishProgress((((float)loadedSize/fileSize)));
response="true";
}
outputStream.close();
}
catch(Exception e)
{
response = e.getMessage();
e.printStackTrace();
}
finally
{
try{
if(outputStream!=null)
outputStream.close();
if(inputStream!=null)
inputStream.close();
}catch(Exception ioex){}
}
return response;
}
}
@Override
protected void onPostExecute(String isdownloaded)
{
if ((vDialog != null) && vDialog.isShowing()) {
vDialog.dismiss();
}
if (isdownloaded.equals("true"))
{
try{
File localpath = new File(getDataFolder(ResourceArrayAdapter.this.getContext()),filename);
if(localpath.exists())
{
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.fromFile(localpath));
ResourceArrayAdapter.this.getContext().startActivity(intent);
}
}
catch(Exception fe)
{
}
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB)
{
new SendDownloadAck(sno,size,webpath).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else
{
new SendDownloadAck(sno,size,webpath).execute();
}
}
else
{
Toast.makeText(ResourceArrayAdapter.this.getContext(),"Download Failed.", Toast.LENGTH_SHORT).show();
}
}
}
答案 0 :(得分:2)
我想知道您为什么要在ProgressDialog
中创建onProgressUpdate()
?没有意义,因为您没有更新进度。
相反,您可以做的是 - 创建ProgressDialog
onPreExecute(..)
并将其展示到onPostExecute(..)
@Override
protected void onPreExecute() {
super.onPreExecute();
vDialog = new ProgressDialog(ResourceArrayAdapter.this.getContext());
vDialog.setMessage("Downloading "+filename+"..");
vDialog.setIndeterminate(false);
vDialog.setCancelable(false);
vDialog.show();
}
// Remove `onProgressUpdate()` completely.
@Override
protected void onPostExecute(String isdownloaded) {
super.onPostExecute();
if ((vDialog != null) && vDialog.isShowing()) {
vDialog.dismiss();
}
}
正如上面评论中提到的 ADM ,您正在做的是 - 当您在当前窗口中已存在时,您正在使用ProgressDialog
创建另一个窗口。因此,先前的引用正在丢失,因此导致leak
。
答案 1 :(得分:1)
在你的情况下
vDialog = new ProgressDialog(ResourceArrayAdapter.this.getContext());
vDialog.setMessage("Downloading "+filename+"..");
vDialog.setIndeterminate(false);
vDialog.setCancelable(false);
每次进行更新时,第一行不应初始化ProgressDialog。您已经在PreExecute()存根中完成了初始化。因此,请删除vDialog = new ProgressDialog(ResourceArrayAdapter.this.getContext());
,如果您继续在try
语句中的同一行中收到错误,请披露stackTrace。而且 ProgressDialog 必须显示在 PreExecuteStub()中,只有更新应该在 onProgressUpdate()
当在尚未创建或已销毁视图时调用View元素的方法时,通常会发生此( Window Leaks )。 例如将OnCLickListener设置为 onAttach 存根中片段上的View,而必须在视图在 onCreateView()存根中充气后放置侦听器。 我建议你看一下你得到这个错误的类的不同可覆盖方法的生命周期,即使问题已经解决了。
答案 2 :(得分:0)
根据我的理解,你可以这样做
@Override
public void onDestroy(){
super.onDestroy();
if ( dialog!=null && dialog.isShowing() ){
dialog.dismiss();
}
}