java - 我的 android 应用程序占用大量内存并停止响应
问题描述
如果可能,请在答案中分享代码 这是我的代码,基本上我认为我的应用程序在一段时间后没有响应,可能是因为冻结的 gui 和高内存使用率,它在后台使用甚至 16.8 MB 的内存。请分享一些技巧,通过这些技巧我可以使我的应用程序简单快速而不会丢失功能。
秒表.java
package com.study.meter;
import android.app.Service;
import android.os.IBinder;
import android.content.Intent;
import android.widget.Toast;
import android.os.Handler;
import java.util.Locale;
import android.app.PendingIntent;
import androidx.core.app.NotificationCompat;
import android.app.NotificationManager;
import android.app.Notification;
import android.content.Context;
public class StopWatch extends Service{
public static StopWatch getStopWatch;
public static int StopWatchSecs;
public static boolean isStopWatchRunning = false;
public static boolean isRunning;
public String StopWatchTime;
private NotificationCompat.Builder builder;
private Intent notificationIntent;
private PendingIntent contentIntent;
private Notification notificaton;
private NotificationManager manager;
private String StopWatchNotificationText,StopWatchNotificationTitle;
@Override
public int onStartCommand (Intent intent, int flags, int startId)
{
return START_CONTINUATION_MASK;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
getStopWatch = this;
}
@Override
public void onDestroy() {
isRunning = false;
Toast.makeText(getBaseContext(),"Destroyed",Toast.LENGTH_SHORT).show();
super.onDestroy();
}
@Override
public void onStart(Intent intent, int startid) {
super.onStart(intent,startid);
isRunning = true;
}
public Handler StopWatchHandler = new Handler();
public Runnable StopWatchRunnable = new Runnable()
{
@Override
public void run()
{
StopWatchSecs++;
int seconds = StopWatchSecs;
int hours = seconds / 3600;
int minutes = (seconds % 3600) / 60;
int secs = seconds % 60;
// Format the seconds into hours, minutes,
// and seconds.
StopWatchTime
= String
.format(Locale.getDefault(),
"%d:%02d:%02d", hours,
minutes, secs);
// if app is running then change counting
if(MainActivity.Stop_Watch!=null && MainActivity.isAppRunning)
{
// Set the text view text.
MainActivity.Stop_Watch.setText(StopWatchTime);
}
addStopWatchNotification("StopWatch",StopWatchTime);
StopWatchHandler.postDelayed(StopWatchRunnable,1000);
}
};
public void Start_Watch()
{
StopWatchHandler.post(StopWatchRunnable);
}
public void Stop_Watch()
{
StopWatchHandler.removeCallbacks(StopWatchRunnable);
}
public String Start_Or_Stop_Watch()
{
String result = "Start";
if(isStopWatchRunning)
{
result = "Resume";
isStopWatchRunning = false;
Stop_Watch();
}
else if(!isStopWatchRunning)
{
result = "Pause";
isStopWatchRunning = true;
Start_Watch();
}
return result;
}
// adding new Handler for notifications to not overload memory
public Handler StopWatchNotificationHandler = new Handler();
public Runnable StopWatchNotificationRunnable;
public void addStopWatchNotification(String title,String text)
{
if(builder==null)
{
builder = new NotificationCompat.Builder(this);
builder
.setSmallIcon(R.drawable.notify_icon)
.setAutoCancel(false)
.setOnlyAlertOnce(true);
}
if(notificationIntent==null)
{
notificationIntent = new Intent(this, MainActivity.class);
}
if(contentIntent==null)
{
contentIntent = PendingIntent.getActivity(this, 0, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
}
if(manager==null)
{
manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
if(StopWatchNotificationRunnable==null)
{
StopWatchNotificationRunnable = new Runnable()
{
@Override
public void run()
{
builder
.setContentTitle(title)
.setContentText(text);
notificaton = builder.build();
notificaton.flags |= Notification.FLAG_NO_CLEAR;
manager.notify(0, notificaton);
}
};
}
StopWatchNotificationText = text;
StopWatchNotificationTitle = title;
StopWatchNotificationHandler.post(StopWatchNotificationRunnable);
}
}
MainActivity.java
package com.study.meter;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.content.Context;
public class MainActivity extends AppCompatActivity
{
public static boolean isAppRunning;
public static TextView Stop_Watch;
public static MainActivity activity;
public Button Start_Watch;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// set content view
setContentView(R.layout.activity_main);
// hide statusbar
getSupportActionBar().hide();
activity = this;
// set the value of StopWatch
Stop_Watch = findViewById(R.id.StopWatch);
Start_Watch = findViewById(R.id.StartWatch);
//if StopWatch service is not running
if(!StopWatch.isRunning)
{
// start the service
startService(new Intent(this, StopWatch.class));
}
}
@Override
public void onResume()
{
super.onResume();
isAppRunning = true;
if(StopWatch.StopWatchSecs!=0)
{
// if stopwatchsecs is not equal to null or 0
if(StopWatch.isStopWatchRunning)
{
// if stopwatch is running in background
Start_Watch.setText("Pause");
}else
{
// if stopwatch is not running in background
Start_Watch.setText("Resume");
}
}
}
@Override
public void onPause()
{
isAppRunning = false;
super.onPause();
}
// "StartWatch" click
public void StartorStop(View v)
{
Button sv = (Button)v;
String StartWatchText = StopWatch.getStopWatch.Start_Or_Stop_Watch();
sv.setText(StartWatchText);
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.study.meter"
android:installLocation="auto">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.StudyMeter">
<service
android:name=".StopWatch"
android:stopWithTask="false"/>
<activity android:name=".MainActivity"
android:configChanges="orientation|screenSize|screenLayout">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="@+id/StopWatch"
android:textSize="65dp"
android:text="0:00:00"
app:layout_constraintBottom_toTopOf="@id/StartWatch"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<Button
android:layout_height="50dp"
android:layout_width="wrap_content"
android:id="@+id/StartWatch"
android:text="Start"
android:onClick="StartorStop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/StopWatch"/>
</androidx.constraintlayout.widget.ConstraintLayout>
解决方案
似乎是架构问题,尝试通过将 Java 代码划分为更多活动来调整更多的 Java 代码,少数活动中的任务过多会导致崩溃和性能下降;)
推荐阅读
- android - 如果我有 Anaconda 3,如何使用 python2 作为解释器运行命令?
- javascript - Mongodb-Nodejs 从数组中拉取元素
- java - 使 spring amqp 消费者停止消费指定类型异常的消息
- .net-core - 在类库依赖中声明函数
- ios - 当我在 SwiftUI 中触摸 mapbox 的注释时如何显示 TextView?
- python-3.x - Classroom API 课程作业提交
- c++ - C++中Boost.Geometry中的多边形变换:平移、旋转、绕线反射
- javascript - 在 date-fns 中获取主名月份名称
- swift - Firebase macOS:为什么使用 Auth.auth().currentUser 会导致 SecurityAgent 对话框弹出,而使用 Auth.auth().signInAnonymously 则不会
- html - 跨浏览器和设备的表单元素(输入)高度一致