在** NonActivity **类中获取android.view.WindowLeaked异常

时间:2018-01-17 05:07:28

标签: android android-arrayadapter progressdialog

当进度对话框可见时按下主页按钮时出现以下异常。我已经浏览了很多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();
            }

         }

    }

3 个答案:

答案 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()

中进行

查看this post

在尚未创建或已销毁视图时调用View元素的方法时,通常会发生此( Window Leaks )。 例如将OnCLickListener设置为 onAttach 存根中片段上的View,而必须在视图在 onCreateView()存根中充气后放置侦听器。 我建议你看一下你得到这个错误的类的不同可覆盖方法的生命周期,即使问题已经解决了。

答案 2 :(得分:0)

根据我的理解,你可以这样做

    @Override
    public void onDestroy(){
    super.onDestroy();
    if ( dialog!=null && dialog.isShowing() ){
        dialog.dismiss();
    }
}