This Handler class should be static or leaks might occur (com.test.test3.ui.MainActivity.1)
Asked Answered
A

2

4

I am new to android and i try to develop a system but when i finish code the handler show this warning

below show the code after I edit, the handler in event ontounch show the warning handler cannot be resolved. I try putting // to ignore the handler at i try run the application and its result in force close.

public class MainActivity extends Activity {



protected static final int STOP = 100;
ImageView iv;
private ProgressBar pb;
LinearLayout ll;
private AnimationDrawable anim;
ScrollView sv;
private SQLiteDatabase db;
private boolean flagscanning = false;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ll = new LinearLayout(this);
    new HandlerClass(this);

            db = SQLiteDatabase.openDatabase(Environment.getExternalStorageDirectory()+"/antivirus.sqlite", null, SQLiteDatabase.OPEN_READONLY);  
            iv = (ImageView) this.findViewById(R.id.imageView1);
                    //扫描病毒进度条
            pb = (ProgressBar) this.findViewById(R.id.progressBar1);
            ll = (LinearLayout) this.findViewById(R.id.ll);
                    //设置ImageView背景资源为动画文件
            iv.setBackgroundResource(R.drawable.bg);
                    //sv用来显示病毒的扫描结果
            sv = (ScrollView) this.findViewById(R.id.scrollView1);
            anim = (AnimationDrawable) iv.getBackground();
}

private static class HandlerClass extends Handler{
    private final WeakReference<MainActivity> mTarget;
    public HandlerClass(MainActivity context){
        mTarget = new WeakReference<MainActivity>((MainActivity) context);
    }

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        MainActivity target = mTarget.get();
         if(msg.what==STOP){
             target.ll.removeAllViews();
             //anim.stop();

             }
         String str = (String) msg.obj; 
         TextView tv = new TextView(target);
         tv.setText(str);
         target.ll.setOrientation(LinearLayout.VERTICAL);
         target.ll.addView(tv);
         //sv.scrollBy(0, 20);

        System.out.println(str);

    }
};


@Override
public boolean onTouchEvent(MotionEvent event) {
    //如果程序正在杀毒过程中,拒绝再次启动杀毒线程
    if(flagscanning){
        return false;
    }

    //如果用户触摸屏幕,则开启杀毒线程  
    if (event.getAction() == MotionEvent.ACTION_UP) {
        flagscanning= true;
        anim.start();
        new Thread() {
            public void run() {
                // 获取每一个应用程序的签名,签名须与数据库的签名想比较
                List<PackageInfo> infos = getPackageManager()
                        .getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_SIGNATURES);
                //设置进度条的扫描范围
                pb.setMax(infos.size());
                int total = 0;
                int virustotal = 0;//设置初始病毒数为0
                for (PackageInfo info : infos) {
                    total++;
                    try {
                        sleep(20);//只为便于观察扫描效果和进度,无实质作用
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Message msg = Message.obtain();
                    msg.obj = "正在扫描" + info.packageName;
                    _handler.sendMessage(msg);_
                    Signature[] signs = info.signatures;
                    String str = signs[0].toCharsString();

                    String md5 = MD5Encoder.encode(str);
                    //将应用程序签名与数据库中保存的签名进行比较,如果相一致,则使病毒数加1,并通过handler在界面显示病毒包名
                    Cursor cursor = db.rawQuery("select desc from datable where md5=?",new String[] { md5 });
                    if (cursor.moveToFirst()) {
                        String desc = cursor.getString(0);
                        msg = Message.obtain();
                        msg.obj = info.packageName + ": " + desc;
                        _handler.sendMessage(msg);_
                        virustotal++;
                    }
                    cursor.close();
                    pb.setProgress(total);

                }
                Message msg = Message.obtain();
                msg.what = STOP;
                msg.obj = "扫描完毕 ,共发现" + virustotal + "个病毒";
                _handler.sendMessage(msg);_
                flagscanning = false;
                pb.setProgress(0);
            };
        }.start();
    }
    return super.onTouchEvent(event);
}

@Override
protected void onDestroy() {
    if (db.isOpen())
        db.close();
    super.onDestroy();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}
}
Asbestos answered 27/7, 2013 at 15:18 Comment(2)
make your handler class static. #3107412Huguenot
Declare HanderClass hc as a class member. then in onCreate replace new HandlerClass(this); by hc = new HandlerClass(this);. And instead of handler.sendMessage use hc.sendMessage.Huguenot
H
10

Make your handler a static class.

The warning is a lint warning. You can disable the warning but its a useful info

Here's a list of Lint Check

http://tools.android.com/tips/lint-checks

Quoting from the source @

http://android-developers.blogspot.in/2009/01/avoiding-memory-leaks.html

Avoid non-static inner classes in an activity if you don't control their life cycle, use a static inner class and make a weak reference to the activity inside.

The solution to this issue is to use a static inner class with a WeakReference to the outer class, as done in ViewRoot and its W inner class for instance.

Also check this discussion on android developers group. Check the solution by Romain Guy

https://groups.google.com/forum/#!topic/android-developers/1aPZXZG6kWk

Example from Romain Guy's solution from the above link

 class OuterClass { 
 class InnerClass { 
  private final WeakReference<OuterClass> mTarget; 

   InnerClass(OuterClass target) { 
    mTarget = new WeakReference<OuterClass>(target); 
  } 

  void doSomething() { 
  OuterClass target = mTarget.get(); 
  if (target != null) target.do(); 
   }

Edit:

Example:

public class MainActivity extends Activity {

      LinearLayout ll;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ll = new LinearLayout(this);
        new HandlerClass(this);
    }
       private static class HandlerClass extends Handler{
           private final WeakReference<MainActivity> mTarget; 
        public HandlerClass(MainActivity context)
        {
             mTarget = new WeakReference<MainActivity>((MainActivity) context);

        }

            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                MainActivity target = mTarget.get(); 
                if (target != null) 
                 if(msg.what==1){
                     target.ll.removeAllViews();
                    // anim.stop();

                     }
                 String str = (String) msg.obj;
                 TextView tv = new TextView(target);
                 tv.setText(str);
                 target.ll.setOrientation(LinearLayout.VERTICAL);
                 target.ll.addView(tv);
                 //sv.scrollBy(0, 20);

                System.out.println(str);

            }

        };
}

Correct me if the above is wrong or has some issues.

You can also check this blog by Alex Lockwood

http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html

Huguenot answered 27/7, 2013 at 15:27 Comment(10)
i try the Romain guy's solution from the link you given at the end of the line 'if(target !=null) target.do()' the do occur error message Syntax error on token "do", super expected <br/> howcome this is happening ??Asbestos
@chukokwann and what's wrong with that?. it should work. post your updated code.Huguenot
how come I can't comment in code format even i put 'code' ''public class MainActivity extends Activity { private Handler handler = new Handler() { private final WeakReference<MainActivity> mTarget; Handler(MainActivity target) { mTarget = new WeakReference<MainActivity>(target); } void doSomething(){ MainActivity target = mTarget.get(); if (target != null ) target.do(); } public void handleMessage(Message msg) { super.handleMessage(msg); if(msg.what==STOP){ ll.removeAllViews(); anim.stop(); } } }; ''Asbestos
@chukokwann try as the edited post. also check the last link posted in the answer.Huguenot
after I edit the code the handler warning disappear but the handler I use in my ontouch event pop out handler cannot be resolved warningAsbestos
erm how to add code in the comment ?? i try use 'code' but fail to post code like what you didAsbestos
don't post code in comment edit your question put it under edit section.Huguenot
sorry never think of it i first time post question here sorry for any inconvenience. I edit the code in my question already.Asbestos
@chukokwann Declare HanderClass hc as a class member. then in onCreate replace new HandlerClass(this); by hc = new HandlerClass(this);. And instead of handler.sendMessage use hc.sendMessage.Huguenot
thank you so much it works for it finally. been struggle for this problem for quite long. Really thanks a lot.Asbestos
J
1

When you define an anonymous inner class like that, the class itself is redefined for every instance of MainActivity. Apparently, the Android SDK flags that as having the potential to leak those class definitions. The simplest solution is to make it a static inner class that takes a reference to MainActivity in the constructor:

public class MainActivity extends Activity {
    //Fields and methods of MainActivity...
    private static final class MainHandler extends Handler {
        private final MainActivity caller;
        private MainHandler(final MainActivity caller) { this.caller = caller; }
        @Override public void handleMessage(Message msg) { //Your existing logic }
    }
}
Joly answered 27/7, 2013 at 15:22 Comment(3)
after I edit the code it occur Illegal modifier for the local class MainHandler; only abstract or final is permitted at the mainhandler and Cannot make a static reference to the non-static field happen in the handlerMessage I try change to private static LinearLayout ll; but still cant fix it below show the code after editAsbestos
public class MainActivity extends Activity { private Handler handler = new Handler() { private static final class MainHandler extends Handler { private final MainActivity caller; private MainHandler(final MainActivity caller) { this.caller = caller; } @Override public void handleMessage(Message msg) { } ll.setOrientation(LinearLayout.VERTICAL); } } }; howcome I cnat comment code line like Tom G did even i already put ` code `Asbestos
@Huguenot I try the method tom G suggest and after that it pop up a illegal modifier for the local class mainhandler, only abstratc or final is permitted. and the value declare and use in the handleMessage have to change to static valueAsbestos

© 2022 - 2024 — McMap. All rights reserved.