了解Android内存消耗

时间:2016-11-02 03:03:26

标签: android performance memory

我是Android开发的新手,我想了解为什么我的应用程序在启动时会使用这么多内存。现在,它开始使用18MB内存(使用Android Studio中的内存监视器)。我已将Firebase Analytics和Admob添加到其中。我担心这些是使用大量内存的罪魁祸首。

通过深入挖掘,我发现SharedPreferenceImpl及其子对象(FastXmlSerializer和ByteBuffer)占用了50%的内存!我很震惊。接下来,我尝试查看哪个线程正在生成这些对象。我发现线程名称是“thread-1-pool-1”。

这是负责创建大量内存的堆栈跟踪:

at java.nio.ByteBuffer.allocate(ByteBuffer.java:56) 
at com.android.internal.util.FastXmlSerializer.<init>(FastXmlSerializer.java:62)    
at com.android.internal.util.XmlUtils.writeMapXml(XmlUtils.java:188)    
at android.app.SharedPreferencesImpl.writeToFile(SharedPreferencesImpl.java:600)    
at android.app.SharedPreferencesImpl.-wrap2(SharedPreferencesImpl.java) 
at android.app.SharedPreferencesImpl$2.run(SharedPreferencesImpl.java:515)  
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)  
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)  
at java.lang.Thread.run(Thread.java:818)    

我有一个LoopThread,它调用服务中的方法。我想知道这是否会导致大量内存消耗。我的服务类和循环线程不包含对SharedPreferences的引用。所以,我很困惑为什么会这样。任何指针都会受到赞赏。

代码可能不是很干净而且很长。但在这里。这个应用程序的想法是在按下电源按钮时调出屏幕保护程序。

这是服务类。

//SaverService.java
@Override
public void onCreate() {
    Log.d("SaverService","Created saver service...");
    super.onCreate();

    loopThread = new LoopThread();
    loopThread.createHandler(this);
    loopThread.start();

    startSaverMethod();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Intent notificationIntent = new Intent(this, StartSaver.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
                                                        .setSmallIcon(R.drawable.pokeball)
                                                        .setContentTitle("Go-Saver's running")
                                                        .setContentText("Tap here to cancel")
                                                        .setContentIntent(pendingIntent);
    Notification notification = mBuilder.build();

    startForeground(1001, notification);
    return START_STICKY;
}

//SharedPreference should be a singleton
private void startSaverMethod() {
    //sharedPreferences = getSharedPreferences("GoSaverPrefs", Context.MODE_PRIVATE);

    try {
        //SharedPreferences.Editor editor = sharedPreferences.edit();

        screenBrightness = Settings.System.getInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS);
        previousScreenBrightness = screenBrightness;
        //editor.putInt("screenBrightness", screenBrightness);
       //editor.commit();

        screenBrightnessMode = Settings.System.getInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE);
        previousScreenBrightnessMode = screenBrightnessMode;
        //editor.putInt("screenBrightnessMode",screenBrightnessMode);
        //editor.commit();

        screenOffTimeout = Settings.System.getInt(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT);
        previousScreenOffTimeout = screenOffTimeout;
        //editor.putInt("screenOffTimeout",screenOffTimeout);
        //editor.commit();
    } catch (Settings.SettingNotFoundException e) {
        e.printStackTrace();
    }

    //Registerting receiver
    screenOffReceiver = new ScreenOffReceiver();
    screenOffReceiver.setSaverService(this);
    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_SCREEN_OFF);
    filter.addAction(Intent.ACTION_SCREEN_ON);
    registerReceiver(screenOffReceiver, filter);


    Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, 3600000);

    pressedMillisec = getPressedMillisec();
}



@Override
public void onDestroy() {
    Log.d("SaverService","Destroying saver service...");
    disableSaverSettings();

    //screenOffTimeout = sharedPreferences.getInt("screenOffTimeout", 30000);
    screenOffTimeout = previousScreenOffTimeout;
    Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, screenOffTimeout);
    unregisterReceiver(screenOffReceiver);

    removeScreenSaver();
    //sharedPreferences = null;
    windowManager = null;
    screenOffReceiver = null;

    Message killMessage = loopThread.handler.obtainMessage(LoopThread.KILL);
    loopThread.handler.sendMessage(killMessage);
    loopThread.handler.getLooper().quit();

    super.onDestroy();
    System.gc();
}

public boolean isScreenSaver() {
    if(screenSaver != null) {
        return screenSaver.isShown();
    } else {
        return false;
    }
}

private boolean isSaverBrightness() {
    try {
        int brightness = Settings.System.getInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS);
        int brightnessMode = Settings.System.getInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE);

        return brightness == 1 && brightnessMode == Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL;
    } catch (Exception e) {
        Log.e("SaverService", "Cannot get brightness");
        return false;
    }
}

public void startScreenSaverAsync() {
    Message onMessage = loopThread.handler.obtainMessage(LoopThread.ON);
    loopThread.handler.sendMessage(onMessage);
}

public void startScreenSaver() {
    Log.d("SaverService","######################################");

    boolean isRightState = !isScreenSaver() && !isSaverBrightness();
    if (!isRightState) {
        Log.e("SaverService","Invalid state. Stopping service");
        stopSelf();
    }

    long currentMillisec = getPressedMillisec();
    if (currentMillisec - pressedMillisec < 2000) {
        Log.d("SaverService","Pressed too fast. Ignoring the second press.");
        return;
    }

    //Creating screenSaver
    windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
    LayoutInflater li = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
    screenSaver = li.inflate(R.layout.screen_saver, null);

    long startTime = System.currentTimeMillis();
    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
            WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
            WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
            WindowManager.LayoutParams.FLAG_FULLSCREEN |
            WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |
            WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR |
            View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
            View.SYSTEM_UI_FLAG_IMMERSIVE,
            PixelFormat.TRANSLUCENT);
    long totalTime = System.currentTimeMillis() - startTime;
    Log.d("SaverService","params Time: " + totalTime);

    startTime = System.currentTimeMillis();
    enableSaverSettings();
    totalTime = System.currentTimeMillis() - startTime;
    Log.d("SaverService","enableSaverSettings Time: " + totalTime);

    startTime = System.currentTimeMillis();
    removeScreenSaver();
    totalTime = System.currentTimeMillis() - startTime;
    Log.d("SaverService","removeScreenSaver Time: " + totalTime);

    Log.d("SaverService", "Adding Screen Saver");
    startTime = System.currentTimeMillis();
    windowManager.addView(screenSaver, params);
    totalTime = System.currentTimeMillis() - startTime;
    Log.d("SaverService","addView Time: " + totalTime);

    Log.d("SaverService", "Turning On Screen");
    startTime = System.currentTimeMillis();
    turnOnScreen(this);
    totalTime = System.currentTimeMillis() -startTime;
    Log.d("SaverService","turnOnScreen Time: " + totalTime);

    pressedMillisec = getPressedMillisec();
    Log.d("SaverService", "Current time - " + pressedMillisec);
    Log.d("SaverService","######################################");
}

public void stopScreenSaverAsync() {
    Message offMessage = loopThread.handler.obtainMessage(LoopThread.OFF);
    loopThread.handler.sendMessage(offMessage);
}

public void stopScreenSaver() {
    Log.d("SaverService","######################################");
    long currentMillisec = getPressedMillisec();
    if (currentMillisec - pressedMillisec < 2000) {
        Log.d("SaverService","Pressed too fast. Ignoring the second press.");
        return;
    }

    disableSaverSettings();
    removeScreenSaver();
    turnOnScreen(this);

    pressedMillisec = getPressedMillisec();
    Log.d("SaverService", "Current time - " + pressedMillisec);
    Log.d("SaverService","######################################");
}

private long getPressedMillisec() {
    return Calendar.getInstance().getTimeInMillis();
}

private void removeScreenSaver() {
    try {
        windowManager.removeViewImmediate(screenSaver);
        screenSaver = null;
    } catch (Exception e) {
        Log.w("SaverService", "Could not remove screen saver...");
    }
}

private void enableSaverSettings() {
    Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
    Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, 1);
}

private void disableSaverSettings() {
    screenBrightness = previousScreenBrightness;
    screenBrightnessMode = previousScreenBrightnessMode;
    //screenBrightness = sharedPreferences.getInt("screenBrightness", 50);
    //screenBrightnessMode = sharedPreferences.getInt("screenBrightnessMode", Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
    Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE, screenBrightnessMode);
    Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, screenBrightness);
}

private void turnOnScreen(Context context) {
    //Wait for screen is off
    PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    boolean isScreenOn = pm.isScreenOn();

    while (isScreenOn) {
        try {
            Thread.sleep(2);
            isScreenOn = pm.isScreenOn();
        } catch (Exception e) {
            Log.i("Issue", "Could not sleep...");
        }
    }

    Intent intentNew = new Intent(context.getApplicationContext(), Transparent.class);
    intentNew.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
    context.startActivity(intentNew);
}

这是听取按下电源按钮的类:

public class ScreenOffReceiver extends BroadcastReceiver {
private SaverService saverService = null;
private static boolean anyThreadRunning = false;


void setSaverService(SaverService saverService){
    this.saverService = saverService;
}

@Override
public void onReceive(Context context, Intent intent) {
    runMethod2(context, intent);
}

private void runMethod2(Context context, Intent intent) {
    String action = intent.getAction();
    Log.d("SaverService", action);

    if(anyThreadRunning) {
        Log.d("SaverService","Another thread is using ScreenOffReceiver. Skipping... ");
        return;
    }

    if(action.equals(Intent.ACTION_SCREEN_OFF) && !saverService.isScreenSaver()){
        anyThreadRunning = true;
        Log.d("SaverService","Turning on screen saver.");
        saverService.startScreenSaverAsync();
    }
    else if(action.equals(Intent.ACTION_SCREEN_OFF) && saverService.isScreenSaver()){
        anyThreadRunning = true;
        Log.d("SaverService","Turning off screen saver." );
        saverService.stopScreenSaverAsync();
    }

    anyThreadRunning = false;
}

}

这是循环线程类:

public class LoopThread extends Thread {
public Handler handler = null;
public static final int ON = ScreenOffHandler.ON;
public static final int OFF = ScreenOffHandler.OFF;
public static final int KILL = ScreenOffHandler.KILL;
private SaverService saverService;

public void run(){
    Looper.prepare();
    handler = new ScreenOffHandler(saverService);
    Looper.loop();
}

public void createHandler(SaverService saverService){
    this.saverService = saverService;
}

private static class ScreenOffHandler extends Handler {
    private SaverService saverService;
    public static final int ON = 1;
    public static final int OFF = 0;
    public static final int KILL = -100;

    public ScreenOffHandler(SaverService saverService) {
        this.saverService = saverService;
    }


    public void handleMessage(Message msg) {
        // ...Run in background

        int what = msg.what;
        switch (what){
            case ON:
                saverService.startScreenSaver();
                break;
            case OFF:
                saverService.stopScreenSaver();
                break;
            case KILL:
                saverService = null;
                break;

        }
    }
}

}

0 个答案:

没有答案