窗口泄露在Android应用程序中

时间:2011-05-20 06:35:31

标签: android

我有一个问题,当我使用json解析一个活动时,第一次它在前面运行非常好但第二次当我想运行相同的活动时它返回窗口泄漏错误。这个问题的解决方案是什么。

错误:

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)

代码:

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;
            }
        }

}

1 个答案:

答案 0 :(得分:7)

以下是我认为您遇到的问题模式:

  • 您创建了一项活动。
  • 您生成了一个工作线程,该线程引用了该活动。
  • 活动以某种方式关闭/完成()(很可能是因为用户交互),系统会尝试收集其资源。
  • 然而,该工作线程仍然在运行并且其持有对Activity的引用...因此该活动已“泄露”,并且系统无法在不以潜在危险方式更改/破坏您的应用程序状态的情况下自由回收它。
    • 活动是Android中的重量级对象,(激进的)系统资源管理器需要能够回收它们以确保为用户提供流畅和高效的体验。所以这个'泄漏'被认为是一个错误。

非常重要的是要了解Android以积极的,自以为是的方式回收资源(特别是像正式生命周期管理的Activity这样的框架对象) - 如果泄漏引用,系统会抱怨(而通常在正常的jvm场景中它会是一个你可能永远不会注意到的内存泄漏。

您需要查看工作线程(上面代码中的'checkUpdate')与其父级或产生活动的交互方式。特别是 - 当一个Activity被拆除(finish(),onStop等)时,你很可能需要以某种方式取消或销毁该工作线程。