首先解释下这句话This Handler class should be static or leaks might occur,大致意思就是说:Handler类应该定义成静态类,否则可能导致内存泄露。

具体如何解决,在国外有人提出,如下:

Issue: Ensures that Handler classes do not hold on to a reference to an outer class

In Android, Handler classes should be static or leaks might occur. Messages enqueued on the application thread's MessageQueue also retain their target Handler. If the Handler is an inner class, its outer class will be retained as well. To avoid leaking the outer class, declare the Handler as a static nested class with a WeakReference to its outer class.

大体翻译如下:

Handler 类应该应该为static类型,否则有可能造成泄露。在程序消息队列中排队的消息保持了对目标Handler类的应用。如果Handler是个内部类,那 么它也会保持它所在的外部类的引用。为了避免泄露这个外部类,应该将Handler声明为static嵌套类,并且使用对外部类的弱应用。

使用范例:

  1. static
    class MyHandler extends Handler {
  2.                 WeakReference<PopupActivity> mActivity;
  3.  
     
  4.                 MyHandler(PopupActivity activity) {
  5.                         mActivity = new WeakReference<PopupActivity>(activity);
  6.                 }
  7.  
     
  8.                 @Override
  9.                 public
    void handleMessage(Message msg) {
  10.                         PopupActivity theActivity = mActivity.get();
  11.                         switch (msg.what) {
  12.                         case 0:
  13.                                 theActivity.popPlay.setChecked(true);
  14.                                 break;
  15.                         }
  16.                 }
  17.         };
  18.  
     
  19.         MyHandler ttsHandler = new MyHandler(this);
  20.         private Cursor mCursor;
  21.  
     
  22.         private
    void test() {
  23.                 ttsHandler.sendEmptyMessage(0);
  24.         }

原文:http://www.cnblogs.com/savagemorgan/archive/2013/01/23/2872371.html

疑问:是否有其它解决方法?

这个提示就是由于Handler的直接引用会导致相关的Activity、Service等无法被GC。如果这么弱应用的话,会出现空指针,有其它解决方法?

抽时间研究下。

==================================================================================================================================

原始代码:

  1. public
    class MainActivity extends Activity {
  2.  
  3.    private
    static
    int urlIndex = 0;
  4.    private
    final
    static String TAG = MainActivity.class.getSimpleName();
  5.    private
    static
    final String[] url = {
  6.          "http://vdn.apps.cntv.cn/api/getLiveUrlCommonRedirectApi.do?channel=pa://cctv_p2p_hdcctv1&type=ipad",
  7.          "http://74.82.62.53:1935/liverepeater/13.stream/playlist.m3u8", "http://rtmp.cntv.lxdns.com/live/cctv3/playlist.m3u8", };
  8.  
  9.    private
    static
    final
    int MSG_PLAY = 100;
  10.    private
    static
    final
    int MSG_RUN_ADB = 101;
  11.    Handler playHandler = new Handler() {
  12.       @Override
  13.       public
    void handleMessage(Message msg) {
  14.          switch (msg.what) {
  15.          case MSG_PLAY:
  16.             urlIndex = urlIndex > url.length - 1 ? 0 : urlIndex;
  17.             videoView.setVideoPath(url[urlIndex]);
  18.             ++urlIndex;
  19.             break;
  20.          case MSG_RUN_ADB:
  21.             killMediaServer();
  22.             break;
  23.          }
  24.       }
  25.    };
  26.  
  27.  
  28.  
  29.    @Override
  30.    protected
    void onCreate(Bundle savedInstanceState) {
  31.       super.onCreate(savedInstanceState);
  32.       requestWindowFeature(Window.FEATURE_NO_TITLE);
  33.       HHVideoView.create();
  34.  
  35.       setContentView(R.layout.activity_main);
  36.       videoView = ((HHVideoView) findViewById(R.id.videoView));
  37.       videoView.setOnPreparedListener(mPreparedListener);
  38.       videoView.setOnCompletionListener(mCompletionListener);
  39.       videoView.setOnErrorListener(mOnErrorListener);
  40.  
  41.       playHandler.sendEmptyMessage(MSG_PLAY);
  42.  
  43.    }
  44.  
  45.    private HHVideoView videoView = null;
  46.    private MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
  47.       public
    void onPrepared(MediaPlayer paramMediaPlayer) {
  48.          // playerHandler.sendEmptyMessage(uiAction.MEDIAPLAYER_ONPREPAREED);
  49.          videoView.start();
  50.       }
  51.    };
  52.  
  53.    private MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
  54.       public
    void onCompletion(MediaPlayer paramMediaPlayer) {
  55.  
  56.       }
  57.    };
  58.    private MediaPlayer.OnErrorListener mOnErrorListener = new MediaPlayer.OnErrorListener() {
  59.       public
    boolean onError(MediaPlayer paramMediaPlayer, int paramInt1, int paramInt2) {
  60.  
  61.          return
    false;
  62.       }
  63.    };
  64.  
  65.    @Override
  66.    public
    boolean onCreateOptionsMenu(Menu menu) {
  67.       // Inflate the menu; this adds items to the action bar if it is present.
  68.       return
    true;
  69.    }
  70.  
  71.    public
    boolean onKeyDown(int keyCode, KeyEvent event) {
  72.       if (event.getAction() == KeyEvent.ACTION_DOWN) {
  73.          switch (keyCode) {
  74.  
  75.          case KeyEvent.KEYCODE_0:
  76.  
  77.             playHandler.sendEmptyMessage(MSG_RUN_ADB);
  78.             break;
  79.  
  80.          case KeyEvent.KEYCODE_DPAD_DOWN:
  81.          case KeyEvent.KEYCODE_DPAD_UP:
  82.  
  83.             playHandler.sendEmptyMessage(MSG_PLAY);
  84.             break;
  85.          }
  86.       }
  87.       return
    super.onKeyDown(keyCode, event);
  88.  
  89.    }
  90.  
  91. }

修改后的代码:

  1. //activity code
  2. public
    class MainActivity extends Activity {
  3.  
  4.    private
    static
    int urlIndex = 0;
  5.    private
    final
    static String TAG = MainActivity.class.getSimpleName();
  6.    private
    static
    final String[] url = {
  7.          "http://vdn.apps.cntv.cn/api/getLiveUrlCommonRedirectApi.do?channel=pa://cctv_p2p_hdcctv1&type=ipad",
  8.          "http://74.82.62.53:1935/liverepeater/13.stream/playlist.m3u8", "http://rtmp.cntv.lxdns.com/live/cctv3/playlist.m3u8", };
  9.  
  10.    PlayHandler playHandler ;
  11.  
  12.  
  13.  
  14.    @Override
  15.    protected
    void onCreate(Bundle savedInstanceState) {
  16.       super.onCreate(savedInstanceState);
  17.       requestWindowFeature(Window.FEATURE_NO_TITLE);
  18.       HHVideoView.create();
  19.  
  20.       setContentView(R.layout.activity_main);
  21.       videoView = ((HHVideoView) findViewById(R.id.videoView));
  22.       videoView.setOnPreparedListener(mPreparedListener);
  23.       videoView.setOnCompletionListener(mCompletionListener);
  24.       videoView.setOnErrorListener(mOnErrorListener);
  25.  
  26.       playHandler.sendEmptyMessage(PlayHandler.MSG_PLAY);
  27.  
  28.    }
  29.  
  30.    private HHVideoView videoView = null;
  31.    private MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
  32.       public
    void onPrepared(MediaPlayer paramMediaPlayer) {
  33.          // playerHandler.sendEmptyMessage(uiAction.MEDIAPLAYER_ONPREPAREED);
  34.          videoView.start();
  35.       }
  36.    };
  37.  
  38.    private MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
  39.       public
    void onCompletion(MediaPlayer paramMediaPlayer) {
  40.  
  41.       }
  42.    };
  43.    private MediaPlayer.OnErrorListener mOnErrorListener = new MediaPlayer.OnErrorListener() {
  44.       public
    boolean onError(MediaPlayer paramMediaPlayer, int paramInt1, int paramInt2) {
  45.  
  46.          return
    false;
  47.       }
  48.    };
  49.  
  50.    @Override
  51.    public
    boolean onCreateOptionsMenu(Menu menu) {
  52.       // Inflate the menu; this adds items to the action bar if it is present.
  53.       return
    true;
  54.    }
  55.  
  56.    public
    boolean onKeyDown(int keyCode, KeyEvent event) {
  57.       if (event.getAction() == KeyEvent.ACTION_DOWN) {
  58.          switch (keyCode) {
  59.  
  60.          case KeyEvent.KEYCODE_0:
  61.  
  62.             playHandler.sendEmptyMessage(PlayHandler.MSG_RUN_ADB);
  63.             break;
  64.  
  65.          case KeyEvent.KEYCODE_DPAD_DOWN:
  66.          case KeyEvent.KEYCODE_DPAD_UP:
  67.  
  68.             playHandler.sendEmptyMessage(PlayHandler.MSG_PLAY);
  69.             break;
  70.          }
  71.       }
  72.       return
    super.onKeyDown(keyCode, event);
  73.  
  74.    }
  75.    public
    void setVideoPath() {
  76.       urlIndex = urlIndex > url.length - 1 ? 0 : urlIndex;
  77.       videoView.setVideoPath(url[urlIndex]);
  78.       ++urlIndex;
  79.    }
  80. }

Handler代码:

  1. //handler code
  2. import java.lang.ref.WeakReference;
  3.  
  4. import android.os.Handler;
  5. import android.os.Message;
  6.  
  7. /**
  8.  * @author jevan
  9.  * @version (1.0 at 2013-7-3)
  10.  *
  11.  */
  12. public
    class PlayHandler extends Handler {
  13.    public
    static
    final
    int MSG_PLAY = 100;
  14.    public
    static
    final
    int MSG_RUN_ADB = 101;
  15.    WeakReference<MainActivity> mActivity;
  16.  
  17.    PlayHandler(MainActivity activity) {
  18.       mActivity = new WeakReference<MainActivity>(activity);
  19.    }
  20.  
  21.    @Override
  22.    public
    void handleMessage(Message msg) {
  23.       MainActivity theActivity = mActivity.get();
  24.       if(theActivity == null)
  25.          return;
  26.       switch (msg.what) {
  27.       case MSG_PLAY:
  28.          theActivity.setVideoPath();
  29.          break;
  30.       case MSG_RUN_ADB:
  31.  
  32.          break;
  33.       }
  34.    }
  35. }

个人还是倾向使用独立的Handler(也就是那个外国人的解决方案),上面反映的Activity会被gc掉,导致参数空指针的问题,其实不能算问题。如果Activity被回收掉,那么Handler应该在使用之前对其状态进行判断。

个人推荐这个解决方法,当然代码会多两行。

This Handler class should be static or leaks might occur Android的更多相关文章

  1. Android“This Handler class should be static or leaks might occur”警告的处理方法

    此文属于转载! 最近用到handle在线程中改变UI,会跟给出“This Handler class should be static or leaks might occur”的警告,网上看了很多解 ...

  2. Android - This Handler class should be static or leaks might occur.

    今天学习了使用 HTTP协议,从Android客户端往Tomcat服务器端以GET发送请求,途中无意中发现自己写的Handler类被Android提示:This Handler class shoul ...

  3. This Handler class should be static or leaks might occur(null) 解决办法 (转)

    原文链接:http://blog.csdn.net/wuleihenbang/article/details/17126371 首先解释下这句话This Handler class should be ...

  4. android之lint警告This Handler class should be static or leaks might occur

    更新到adt2.0的开发者们可能会在handler上发现这么一条警告:This Handler class should be static or leaks might occur . 首先在ADT ...

  5. This Handler class should be static or leaks might occur,Handler和Context使用的注意事项!

    Android中.在使用到Handler的时候,假设按例如以下代码编写: private Handler handler; @Override public void onCreate(Bundle ...

  6. Handler classes should be static or leaks might occur

    http://droidyue.com/blog/2014/12/28/in-android-handler-classes-should-be-static-or-leaks-might-occur ...

  7. 85、android handler的警告Handler Class Should be Static or Leaks Occur

    转载:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1106/1922.html 在使用Handler更新UI的时候,我是这样写 ...

  8. 【Android】[转] Android Handler应设为static

    android开发中,使用Lint检测时会提示这么一句话 : This Handler class should be static or leaks might occur.意为handler应用s ...

  9. Handler Should be static or leaks Occur?

    解决办法: public class SampleActivity extends Activity { /** * Instances of static inner classes do not ...

随机推荐

  1. 使用Nuget管理dll

    前言 nuget 已经不是什么新东西,它是vs的一个扩展工具,可以让我们在项目中添加.删除.更新引用变得更加快捷方便.现在有许多传统公司对dll的管理还是很落后的,有些甚至时通过发送dll文件,这样做 ...

  2. Javascript学习九

    计时器setInterval() 在执行时,从载入页面后每隔指定的时间执行代码. 语法: setInterval(代码,交互时间); 参数说明: 1. 代码:要调用的函数或要执行的代码串. 2. 交互 ...

  3. 读书笔记 effective c++ Item 23 宁可使用非成员非友元函数函数也不使用成员函数

    1. 非成员非友元好还是成员函数好? 想象一个表示web浏览器的类.这样一个类提供了清除下载缓存,清除URL访问历史,从系统中移除所有cookies等接口: class WebBrowser { pu ...

  4. 利用nginx concat模块合并js css

    前言: nginx-http-concat模块是由淘宝网开发的,现在淘宝网合并js和css正是用这个模块,如链接http://a.tbcdn.cn/??s/kissy/1.2.0/kissy-min. ...

  5. 网络性能测试工具Iperf/Jperf解读

    Iperf 是一个网络性能测试工具.Iperf 可以测试TCP 和UDP 带宽质量.Iperf 可以测量最大TCP 带宽,具有多种参数和UDP 特性. Iperf 可以报告带宽,延时抖动和数据包丢失. ...

  6. c风格字符串,字符串字面值,c++字符串

    C风格字符串:本质上就是以空字符null为结束符的数组 可以简单的理解为:有'\0'的是c风格字符串,无'\0'的是普通字符数组 字符串字面值:是一串常量字符,字符串字面值常量用双引号括起来的零个或多 ...

  7. 2017.3.3自测j纠错题.

    解析:   在jUery中,他的背景颜色依次是红色,绿色,蓝色. 改变的是整个主体部分.<dody></body>. 单击. 2. 解析:  操作元素: html()  获取第 ...

  8. 关于利用input的file属性在页面添加图片的问题

    在页面添加图片涉及到兼容的问题怎么解决兼容问题呢?请看下面分析: 在IE浏览器上面我们能直接通过获取其input的value值来获取其图片的路径. 在火狐和谷歌需要用createObjectURL(( ...

  9. 1212: [HNOI2004]L语言

    1212: [HNOI2004]L语言 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 643  Solved: 252[Submit][Status] ...

  10. app 评分

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #822e0e } p.p2 { margin: 0.0px 0. ...