This handler class must be static or a leak may occur (com.test.test3.ui.MainActivity.1)

I am new to android and I am trying to develop a system, but when I finish the code, the handler shows this warning

the code after editing is shown below, the handler in the ontounch event shows that the warning handler cannot be enabled. I try to put // ignore the handler when I try to start the application and its result is valid to 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; } } 
+3
source share
2 answers

Make your handler a static class.

A warning is a warning. You can turn off the warning, but its useful information

Here is a list of Lint Check

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

Quote from source @

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

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

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

Also check out this discussion in the Android development team. Check Romain Guy's Solution

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

An example from the solution of Romain Guy from the 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 incorrect or has some problems.

You can also check out this blog by Alex Lockwood.

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

+10
source

When you define an anonymous inner class like this, the class itself is overridden for each instance of MainActivity . It appears Android SDK flags have the potential to leak these class definitions. The simplest solution is to make it a static inner class that references 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 } } } 
+1
source

Source: https://habr.com/ru/post/951622/


All Articles