This Handler class should be static or leaks might occur (com.test.test3.ui.MainActivity.1)
android, android-handler, memory-leaks, static-class
Solution
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
Problem
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; } } ```