Sanat Pandey
Sanat Pandey

Reputation: 2609

Window leaked in android app

I have a problem that when I am using json parsing for one activity then first time it is running in front very fine but second time when I want to run the same activity it returns window leaked error. What is the solution for this problem.

Error:

05-20 12:02:14.579: ERROR/WindowManager(321): Activity org.shopzilla.android.search.SearchResultActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@44fab6b8 that was originally added here
05-20 12:02:14.579: ERROR/WindowManager(321): android.view.WindowLeaked: Activity org.shopzilla.android.search.SearchResultActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@44fab6b8 that was originally added here
05-20 12:02:14.579: ERROR/WindowManager(321):     at android.view.ViewRoot.<init>(ViewRoot.java:247)
05-20 12:02:14.579: ERROR/WindowManager(321):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
05-20 12:02:14.579: ERROR/WindowManager(321):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
05-20 12:02:14.579: ERROR/WindowManager(321):     at android.view.Window$LocalWindowManager.addView(Window.java:424)
05-20 12:02:14.579: ERROR/WindowManager(321):     at android.app.Dialog.show(Dialog.java:241)
05-20 12:02:14.579: ERROR/WindowManager(321):     at android.app.ProgressDialog.show(ProgressDialog.java:107)
05-20 12:02:14.579: ERROR/WindowManager(321):     at android.app.ProgressDialog.show(ProgressDialog.java:90)
05-20 12:02:14.579: ERROR/WindowManager(321):     at org.shopzilla.android.search.SearchResultActivity.onCreate(SearchResultActivity.java:126)
05-20 12:02:14.579: ERROR/WindowManager(321):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
05-20 12:02:14.579: ERROR/WindowManager(321):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
05-20 12:02:14.579: ERROR/WindowManager(321):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
05-20 12:02:14.579: ERROR/WindowManager(321):     at android.app.ActivityThread.access$2300(ActivityThread.java:125)
05-20 12:02:14.579: ERROR/WindowManager(321):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
05-20 12:02:14.579: ERROR/WindowManager(321):     at android.os.Handler.dispatchMessage(Handler.java:99)
05-20 12:02:14.579: ERROR/WindowManager(321):     at android.os.Looper.loop(Looper.java:123)
05-20 12:02:14.579: ERROR/WindowManager(321):     at android.app.ActivityThread.main(ActivityThread.java:4627)
05-20 12:02:14.579: ERROR/WindowManager(321):     at java.lang.reflect.Method.invokeNative(Native Method)
05-20 12:02:14.579: ERROR/WindowManager(321):     at java.lang.reflect.Method.invoke(Method.java:521)
05-20 12:02:14.579: ERROR/WindowManager(321):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
05-20 12:02:14.579: ERROR/WindowManager(321):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
05-20 12:02:14.579: ERROR/WindowManager(321):     at dalvik.system.NativeStart.main(Native Method)

Code:

public class SearchGridActivity extends Activity{

    URL url1;
    Bitmap bmp;
    Bundle bundle;
    GridView grid;
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.searchgrid);

        grid = (GridView)findViewById(R.id.Search_Result_Grid);

        final ProgressDialog dialog = ProgressDialog.show(this, "BIZRATE", "Loading.......", true);
                final Handler handler = new Handler() {

                   public void handleMessage(Message msg) {

                        callHereForEff();
                       dialog.dismiss();


                      }
                   };
                   Thread checkUpdate = new Thread() {  
                    public void run() {
                       SearchResult_Json.json_parsing();
                      handler.sendEmptyMessage(0);

                      }
                   };
                checkUpdate.start();



        bundle = getIntent().getExtras();
        EditText et_search_grid = (EditText)findViewById(R.id.txt_search_grid);
        et_search_grid.setText(bundle.getString("keyword"));

        Button btn_list = (Button)findViewById(R.id.btn_searchresult_list);
        Button btn_refine = (Button)findViewById(R.id.btn_RefineSearch);

        btn_refine.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
            Intent intent = new Intent(SearchGridActivity.this,SearchRefine.class);
            startActivity(intent);
            }
        });

        btn_list.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
            Intent intent = new Intent(SearchGridActivity.this,SearchResultActivity.class);
            intent.putExtra("keyword", bundle.getString("keyword"));
            startActivity(intent);
            }
        });

    }


    protected void callHereForEff() {
        grid.setAdapter(new ImageAdapter(this));//Load the GridView
    }


    //Showing Images with TextViews in Grid View
     public class ImageAdapter extends BaseAdapter{
            Context mContext;
            public static final int ACTIVITY_CREATE = 10;
            public ImageAdapter(Context c){
                mContext = c;
            }
            @Override
            public int getCount() {
                // TODO Auto-generated method stub
                return 5;
            }

            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                // TODO Auto-generated method stub
                View v;
                try {
                    url1 = new URL(SearchResultActivity.image_me.get(position));
                } catch (MalformedURLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                try {
                    bmp = BitmapFactory.decodeStream(url1.openConnection().getInputStream());
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                if(convertView==null){
                    LayoutInflater li = getLayoutInflater();
                    v = li.inflate(R.layout.search_result_griditem, null);
                    TextView tv = (TextView)v.findViewById(R.id.txt_SearchResultGrid_Price);
                    tv.setText(SearchResultActivity.min_price.get(position));
                    ImageView iv = (ImageView)v.findViewById(R.id.img_SearchResultGrid_Product);
                    iv.setImageBitmap(bmp);

                }
                else
                {
                    v = convertView;
                }
                return v;
            }
            @Override
            public Object getItem(int arg0) {
                // TODO Auto-generated method stub
                return null;
            }
            @Override
            public long getItemId(int arg0) {
                // TODO Auto-generated method stub
                return 0;
            }
        }

}

Upvotes: 2

Views: 8217

Answers (1)

Mike Repass
Mike Repass

Reputation: 6962

Here is the problematic pattern I think you are encountering:

  • You create an activity.
  • You spawn a worker thread which has references to that activity.
  • The activity is closed / finish()ed somehow (most likely as a result of user interaction), and the system tries to collect its resources.
  • HOWEVER, that worker thread is still running and its holding references to the Activity ... thus the activity has 'leaked' and the system cannot freely reclaim it without altering/corrupting your application state in potentially dangerous ways.
    • Activities are heavyweight objects in Android and the (aggressive) system resource manager needs to be able to reclaim them to ensure a smooth and performant experience for the user. So this 'leak' is considered an error.

It is very important to understand that Android reclaims resources (particularly framework objects like Activity with formal lifecycle management) in an aggressive, opinionated way - if you leak references, the system will complain (whereas typically in a normal jvm scenario it would be a memory leak that you might never notice).

You need to review how your worker threads ('checkUpdate' in the code above) interact with their parent or spawning activity. In particular - when an Activity is torn down (finish(), onStop, etc), most likely you need to cancel or destroy that worker thread somehow.

Upvotes: 7

Related Questions