这几天在写项目的时候用到百度定位功能,决定把这个功能封装一些,编写代码的过程中AS提示了一个可能的内存泄漏警告,如下:
AS的确好用,不但把问题指出,连解决方案都提供了,这个警告的原因是,Handler被声明为内部类后,应该,否则会有内存泄漏的风险。原因是,在程序消息队列中,排队的消息保持了对目标Handler的引用,如果Handler是一个内部类,那么它也会保持其所在外部类的引用,从而造成内存泄漏。解决方法是Handler定义成静态类 在静态类中使用WeakReference对象弱引用的方式对外部类的的成员进行调用。废话不多说,直接上代码:
package com.example.congbai.fundweather.util;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import java.lang.ref.WeakReference;
/**
* Created by fundmarkhua on 2017/3/12
* Email:57525101@qq.com
* 百度地图api封装进行地理定位
*/
public class LocationUtil {
private static final String TAG = "LocationUtil";
private static LocationUtil instance;
private LocationClient mLocationClient;
private LocationClientOption option;
private MyLocationListener myLocationListener;
private BDLocation currentLocation;
private Handler handMessage;
private SharedPreferences sharedPreferences;
private boolean isCanceled;
private LocationUtil() {
}
public static LocationUtil getInstance() {
if (null == instance) {
instance = new LocationUtil();
}
return instance;
}
private void load(Context context) {
mLocationClient = new LocationClient(context);
option = new LocationClientOption();
option.setIsNeedAddress(true);
mLocationClient.setLocOption(option);
myLocationListener = new MyLocationListener();
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
//创建消息
handMessage = new HandlerMessage(instance);
isCanceled = true;
}
public void create(Context context) {
if (context == null) {
return;
}
load(context);
}
/**
* 开始定位
*/
public void start() {
handMessage.sendEmptyMessage(0);
}
/**
* 停止定位
*/
public void stop() {
handMessage.sendEmptyMessage(1);
}
/**
* 重启定位
*/
public void restart() {
handMessage.sendEmptyMessage(2);
}
/**
* 获取定位数据
*/
public BDLocation getLocation() {
return currentLocation;
}
private static class HandlerMessage extends Handler {
WeakReference<LocationUtil> mLocationUtil;
HandlerMessage(LocationUtil locationUtil) {
mLocationUtil = new WeakReference<>(locationUtil);
}
public void handleMessage(Message msg) {
LocationUtil myLocationUtil = mLocationUtil.get();
super.handleMessage(msg);
switch (msg.what) {
case 0:
//开始
myLocationUtil.mLocationClient.registerLocationListener(myLocationUtil.myLocationListener);
myLocationUtil.mLocationClient.start();
myLocationUtil.isCanceled = false;
break;
case 1:
//停止
myLocationUtil.mLocationClient.unRegisterLocationListener(myLocationUtil.myLocationListener);
myLocationUtil.mLocationClient.stop();
myLocationUtil.isCanceled = true;
break;
case 2:
//重启
if (!myLocationUtil.isCanceled) {
myLocationUtil.mLocationClient.unRegisterLocationListener(myLocationUtil.myLocationListener);
myLocationUtil.mLocationClient.stop();
}
myLocationUtil.mLocationClient.registerLocationListener(myLocationUtil.myLocationListener);
myLocationUtil.mLocationClient.start();
myLocationUtil.isCanceled = false;
break;
}
}
}
private class MyLocationListener implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation bdLocation) {
if (bdLocation != null) {
if (bdLocation.getCity() != null){
LogUtil.w(TAG, "地址获取成功" + bdLocation.getCity());
instance.stop();
}
}
@Override
public void onConnectHotSpotMessage(String s, int i) {
}
}
}
关于内存泄漏以及WeakReference相关只是,网络上很多了,这里分享一篇个人认为不错的:
https://zhuanlan.zhihu.com/p/25213586 Android 内存泄漏分析心得