2013-07-27 58 views
3

我是新來的android,我嘗試開發一個系統,但是當我完成代碼時,處理程序顯示此警告這個處理程序類應該是靜態的或者可能發生泄漏(com.test.test3.ui.MainActivity.1)

顯示我編輯後的代碼,事件ontounch中的處理程序顯示警告處理程序無法解析。我試着把//忽略處理程序,我嘗試運行應用程序及其結果強制關閉。

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

讓你的處理程序類的靜態。 http://stackoverflow.com/questions/3106912/why-does-android-prefer-static-classes – Raghunandan

+0

聲明'HanderClass hc'作爲類成員。然後在onCreate中用'hc = new HandlerClass(this);'替換'new HandlerClass(this);'。而不是'handler.sendMessage'使用'hc.sendMessage'。 – Raghunandan

回答

10

讓你處理一個靜態類。

該警告是一個皮棉警告。您可以禁用警告,但它是一個有用的信息

這裏的皮棉列表檢查

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

從源報價@

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

避免在非靜態內部類一個活動,如果你不控制他們的生命週期,使用一個靜態的內部類,並對內部的活動做一個弱引用。

此問題的解決方案是對外部類使用一個帶有WeakReference的靜態內部類,如ViewRoot及其W內部類所示。

另請查看關於android開發人員組的討論。通過羅曼蓋伊檢查解決方案從羅曼蓋伊的解決方案

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

例如,從上面的鏈接

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

編輯:

例子:

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

      } 

     }; 
} 

如果糾正我,以上是錯誤的或有一些問題。

您還可以查看該博客由亞歷克斯·洛克伍德

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

+0

我試着羅恩傢伙的解決方案,從你在該行末尾給出的鏈接'if(target!= null)target.do()'確實發生了錯誤消息令牌「do」的語法錯誤,超預期
howcome正在發生 ?? –

+0

@chukokwann,這有什麼問題?它應該工作。發佈您的更新代碼。 – Raghunandan

+0

怎麼來的,我不能在代碼格式的評論甚至我把「代碼」「」公共類MainActivity擴展活動{ \t \t \t \t私人處理程序處理程序=新的處理程序(){ \t \t私人最終的WeakReference < MainActivity> mTarget; \t \t \t \t處理程序(MainActivity目標){ \t \t \t mTarget =新的WeakReference (目標); \t \t} \t \t \t 空隙\t doSomething的(){ \t \t \t MainActivity目標= mTarget.get(); \t \t \t if(target!= null)target。做(); \t \t} \t \t \t \t \t公共無效的handleMessage(消息MSG){ \t \t \t super.handleMessage(MSG); \t \t \t if(msg.what == STOP){ \t \t \t ll.removeAllViews(); \t \t \t \t anim.stop(); \t \t \t \t \t \t \t \t} \t \t } \t \t \t \t \t \t }; '' –

1

當你定義一個匿名內部類這樣,類本身被重新定義爲MainActivity每個實例。顯然,Android SDK標記爲有可能泄漏這些類定義。最簡單的辦法是讓一個靜態內部類,需要一個參考MainActivity在構造函數中:

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 } 
    } 
} 
+0

我編輯後出現的代碼非法修飾符爲本地類MainHandler;只有抽象或最終是允許在主處理程序,並且不能對發生在handlerMessage中的非靜態字段進行靜態引用我嘗試更改爲私有靜態LinearLayout ll;但仍然無法修復它下面顯示的代碼編輯後 –

+0

'公共類MainActivity擴展活動{ \t \t私人處理程序處理程序=新的處理程序(){ \t私有靜態final類MainHandler擴展了Handler { \t \t私人最終MainActivity調用者; \t \t private MainHandler(final MainActivity caller){ \t \t \t this.caller = caller; \t \t} \t \t \t @Override \t \t \t公共無效的handleMessage(消息MSG){\t} \t \t \t ll.setOrientation(LinearLayout.VERTICAL); \t \t \t \t \t} \t \t \t} \t \t};'howcome我CNAT像湯姆摹註釋代碼行做甚至我已經把''代碼 –

+0

@chukokwann有什麼不對? – Raghunandan

相關問題