黄家琛 2019-07-22 19:40 采纳率: 50%
浏览 449
已采纳

关于安卓内存泄露的问题

小弟最近在做一个小项目,基本上功能完成了,但发现在程序运行了几分钟后会自动退出,打印的日志信息如下:
图片说明

然后又通过对程序进行注释后发现在将从服务器获取数据的功能注释掉后这个问题解决了,所以觉得问题应该是出在这一块,在这个功能中循环调用的函数有关于对象以及线程,不知是否是这一块的问题,现将整个程序贴上求大神帮忙看看:
MainActivity中:

package com.example.gsontest;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Toast;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.MyLocationConfiguration;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.utils.CoordinateConverter;

import org.json.JSONObject;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity {
    private MapView mapView;
    private BaiduMap baiduMap;
    public LocationClient mLocationClient;
    public static String responseData;
    public double dvalueX;
    public double dvalueY;
    private boolean isFirstLocate = true;
    public int mXDirection;
    //方向类的对象
    public MyOrientationListener myOrientationListener;

    @Override
    //该函数主要是进行Activity初始化
    protected void onCreate(Bundle savedInstanceState) {
        Log.i("MainActivity","进入到onCreate函数中进行初始化");
        super.onCreate(savedInstanceState);
        //实例化对象
        mLocationClient = new LocationClient(getApplicationContext());
        //注册监听器
        mLocationClient.registerLocationListener(new MyLocationListener());
        //初始化SDK
        SDKInitializer.initialize(getApplicationContext());
        setContentView(R.layout.activity_main);
        mapView = (MapView) findViewById(R.id.bmpView);
        baiduMap = mapView.getMap();
        baiduMap.setMyLocationEnabled(true);

        //尝试在监听按钮之前进行权限的允许
        List<String> permissionList = new ArrayList<>();
        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);
        }
        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.READ_PHONE_STATE);
        }
        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        }
        if (!permissionList.isEmpty()) {
            String[] permission = permissionList.toArray(new String[permissionList.size()]);
            ActivityCompat.requestPermissions(MainActivity.this, permission, 1);
            requestLocation();
        } else {
            requestLocation();
        }
    }

    private void requestLocation() {
        Log.i("MainActivity", "进入到requestLocation函数中");
        initLocation();
        //定位开始
       initOrientationListener();
       myOrientationListener.start();
        mLocationClient.start();

    }

    private void initLocation() {
        Log.i("MainActivity", "跳进了initLocation定位初始化函数中");
        LocationClientOption option = new LocationClientOption();
        option.setCoorType("bd09ll");
        option.setScanSpan(1000);
        mLocationClient.setLocOption(option);
    }

    private void initOrientationListener() {
        Log.i("MainActivity", "跳进了initOrientationListener方向初始化函数中");
        myOrientationListener = new MyOrientationListener(getApplicationContext());
        myOrientationListener.setOnOrientationListener(new MyOrientationListener.OnOrientationListener() {
            @Override
            public void onOrientationChanged(float x) {
                mXDirection = (int) x;
            }
        });
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        Log.i("MainActivityActivity","进入onRequestPermissionResult函数中");
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0) {
                    for (int result : grantResults) {
                        if (result != PackageManager.PERMISSION_GRANTED) {
                            Toast.makeText(this, "必须同意所有权限", Toast.LENGTH_LONG).show();
                            finish();
                            return;
                        }
                    }
                   // sendRequestWithOkHttp();
                } else {
                    Toast.makeText(this, "发生未知错误", Toast.LENGTH_LONG).show();
                    finish();
                }
                break;
            default:
        }
    }

    //定位监听器的类
    public class MyLocationListener implements BDLocationListener {
        @Override
        public void onReceiveLocation(BDLocation location) {
            Log.i("MainActivity", "跳进了onReceiveLocation函数中");
            if (location.getLocType() == BDLocation.TypeGpsLocation || location.getLocType() == BDLocation.TypeNetWorkLocation) {
                navigateTo(location);
            }

        }
    }


    private void navigateTo(BDLocation location) {
        Log.i("MainActivity", "跳进了navigateTo函数中");
        //从服务器上获取实时的硬件位置
        sendRequestWithOkHttp();
        //将获取到的数据进行解析
        ObjectJson(responseData);
        //将获取到的经纬度信息在地图上进行显示
        displayLocation(dvalueX, dvalueY);

        //初次定位确定缩放尺寸,后面不改变便于手动伸缩
        if (isFirstLocate) {
            BitmapDescriptor myBitMap = BitmapDescriptorFactory.fromResource(R.drawable.icon_reddirection);
            MyLocationConfiguration myLocationConfiguration = new MyLocationConfiguration(MyLocationConfiguration.LocationMode.NORMAL, true, myBitMap);
            baiduMap.setMyLocationConfiguration(myLocationConfiguration);
            LatLng la = new LatLng(location.getLatitude(), location.getLongitude());
            MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(la);
            baiduMap.animateMapStatus(update);
            update = MapStatusUpdateFactory.zoomTo(18f);
            baiduMap.animateMapStatus(update);
            isFirstLocate = false;
        }
        //将手机当前位置的小蓝点显示在屏幕上
        MyLocationData.Builder locationBuilder = new MyLocationData.Builder();
        locationBuilder.latitude(location.getLatitude());
        locationBuilder.longitude(location.getLongitude());
        //将要执行获取方向方法
        locationBuilder.direction(mXDirection);
        MyLocationData locationData = locationBuilder.build();
        baiduMap.setMyLocationData(locationData);
    }

    //重写三个方法以对mapView进行管理,保证资源可以及时释放
    @Override
    protected void onResume() {
        Log.i("MainActivity", "进入到onResume函数中");
        super.onResume();
        mapView.onResume();
    }

    @Override
    protected void onPause() {
        Log.i("MainActivity", "进入到onPause函数中");
        super.onPause();
        mapView.onPause();
    }

    @Override
    protected void onDestroy() {
        Log.i("MainActivity", "进入到onDestroy函数中");
        super.onDestroy();
        mapView.onDestroy();
        baiduMap.setMyLocationEnabled(false);
        mLocationClient.stop();
        //停止方向监听
        myOrientationListener.stop();
    }

    private void sendRequestWithOkHttp() {
        Log.i("MainActivity", "跳进了sendRequestWithOkHttp方法中");
        new Thread(new Runnable() {
            @Override
            //重写run方法,run方法规定了该线程的具体使命
            public void run() {
                Log.i("MainActivity","跳进OkHttp的子线程中");
                try {
                    OkHttpClient client = new OkHttpClient();
                    Request request = new Request.Builder()
                            .url("https://huadiheal.cn/animal/latest_data")
                            .build();
                    Response response = client.newCall(request).execute();
                    responseData = response.body().string();

                    // ObjectJson(responseData);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            //创建后线程仅是占有内存资源,在JVM管理的线程中还没有这个资源,要调用父类的start方法通知JVM
        }).start();


    }

    private void ObjectJson(String responseData) {
        Log.i("MainActivity", "跳进了ObjectJson函数中");
        try {
            JSONObject jsonObject = new JSONObject(responseData);

            JSONObject valueX = jsonObject.getJSONObject("value_x");
            JSONObject valueY = jsonObject.getJSONObject("value_y");

            Iterator<String> iteratorX = valueX.keys();
            while (iteratorX.hasNext()) {
                String valueXkey = iteratorX.next();
                String valueXValue = valueX.getString(valueXkey);
                String valueYValue = valueY.getString(valueXkey);
                dvalueX = Double.parseDouble(valueXValue);
                dvalueY = Double.parseDouble(valueYValue);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void displayLocation(double dvalueX, double dvalueY) {
        Log.i("MainActivity", "进入displayLocation中");
        LatLng latLng = new LatLng(dvalueY, dvalueX);
        //进行坐标转换
        CoordinateConverter converter = new CoordinateConverter()
                .from(CoordinateConverter.CoordType.GPS)
                .coord(latLng);
        LatLng dLatlng = converter.convert();

        //进行刷新时,先清除上一次的overlay
        baiduMap.clear();
        //现添加Marker将位置在地图上标出来
        BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(R.drawable.icon_niu32);
        OverlayOptions option = new MarkerOptions()
                .position(dLatlng)
                .icon(bitmap);

        baiduMap.addOverlay(option);
    }
}

方向传感器的监听类如下:

package com.example.gsontest;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;

//方向监听器的类
public class MyOrientationListener implements SensorEventListener {
    private SensorManager mySensorManager;
    private Sensor mySensor;
    private Context myContext;
    private float lastX;

    private OnOrientationListener myOnOrientationListener;

    public void start(){
        Log.i("MainActivity", "跳进了方向类的start函数中");
        mySensorManager = (SensorManager) myContext.getSystemService(Context.SENSOR_SERVICE);
        if(mySensorManager!=null){
            mySensor = mySensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
        }
        if(mySensor!=null){
            //SENSOR_UI可能会出现数据滞后现象,若后期数据滞后则改成别的类型
            mySensorManager.registerListener(this,mySensor,SensorManager.SENSOR_DELAY_NORMAL);
        }
    }

    //接触注册方向传感器监听事件,即对onDestroy中所引方法的实现
    public void stop(){
        Log.i("MainActivity","跳进方向类的stop函数中");
        mySensorManager.unregisterListener(this);
    }

    //方向传感器的一个构造函数
    public MyOrientationListener(Context myContext){
        this.myContext = myContext;
    }

    @Override
    public void onAccuracyChanged(Sensor sensor,int accuracy){}

    //监听方向变化
    @Override
    public void onSensorChanged(SensorEvent event){
        Log.i("MainActivity","跳进了onSensorChanged函数中");
        if(event.sensor.getType()==Sensor.TYPE_ORIENTATION){
            float x = event.values[SensorManager.DATA_X];

            if (Math.abs(x-lastX)>1.0){
                if(myOnOrientationListener!=null){
                    myOnOrientationListener.onOrientationChanged(lastX);
                }
            }
            lastX = x;
        }
    }

    public void setOnOrientationListener(OnOrientationListener myOrientationListener){
        this.myOnOrientationListener = myOrientationListener;
    }
    public interface OnOrientationListener{
        void onOrientationChanged(float x);
    }

}

恳请大神帮忙看下程序谢谢!!

  • 写回答

1条回答 默认 最新

  • 关注
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 java 的protected权限 ,问题在注释里
  • ¥15 这个是哪里有问题啊?
  • ¥15 关于#vue.js#的问题:修改用户信息功能图片无法回显,数据库中只存了一张图片(相关搜索:字符串)
  • ¥15 texstudio的问题,
  • ¥15 spaceclaim模型变灰色
  • ¥15 求一份华为esight平台V300R009C00SPC200这个型号的api接口文档
  • ¥15 就很莫名其妙,本来正常的Excel,突然变成了这种一格一页
  • ¥15 字符串比较代码的漏洞
  • ¥15 欧拉系统opt目录空间使用100%
  • ¥15 ul做导航栏格式不对怎么改?