我是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;
}
}
}
}