应用被系统回收导致崩溃的解决方案

当应用被系统回收后,重新打开可能导致静态变量空指针异常,从而引起应用崩溃。例如,NewsActivity中未缓存的集合变量会导致问题。解决方案包括对可能引发崩溃的变量进行缓存,避免过度依赖静态变量,或者检查强杀标志并主动重启应用来应对系统回收。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

应用被系统回收导致崩溃的解决方案

应用长时间被搁置后台,如果应用进程被系统回收(内存不足),重新打开应用时,会造成静态变量空指针,进而应用崩溃。

有以下简单的示例代码:

BaseApplication

public class BaseApplication extends Application {

public static int forceKill = -1;

public static List<String> news;

@Override
public void onCreate() {
    super.onCreate();
}

public static void initNews() {
    List<String> news = new ArrayList<>();
    news.add("1");
    news.add("21");
    news.add("321");
    BaseApplication.news = news;
}

MainActivity(Launcher)

public class MainActivity extends Activity {

    private Button btnJump;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnJump = findViewById(R.id.btn_jump);
        //正常启动,置为0
        forceKill = 0;
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Log.d("log", "MainAct onRestoreInstanceState");
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.d("log", "MainAct onSaveInstanceState");
    }

    @Override
    protected void onResume() {
        super.onResume();
        btnJump.setText("Jump Jump");
        initNews();
    }

    public void jump(View view) {
        Intent intent = new Intent(this, NewsActivity.class);
        startActivity(intent);
    }
}

NewsActivity

public class NewsActivity extends Activity {

    private Button btnNews;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_news);
        btnNews = findViewById(R.id.btn_news);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        news = savedInstanceState.getStringArrayList("news");
        Log.d("log", "NewsAct onRestoreInstanceState");
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.d("log", "NewsAct onSaveInstanceState");
        /*如果不对数据做缓存,恢复页面的时候变量news空指针崩溃*/
        outState.putStringArrayList("news", (ArrayList<String>) news);
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d("log", "NewsAct onResume : IsForceKilled ? " + (forceKill == -1));
        btnNews.setText("News: " + news.get(0));
    }
}

复原这个问题的操作流程和日志

操作:
Launched App.
跳转 NewsAct.

打印日志:
D/log: NewsAct  onResume :  IsForceKilled ?  false
D/log: MainAct onSaveInstanceState

操作:
按Home键.

打印日志:
D/log: News Act onSaveInstanceState: 

操作:
点击LogCat中 [Terminate Application] 按钮,回收App所在进程.
然后点击App桌面图标重新启动.

打印日志:
D/log: NewsAct onRestoreInstanceState
D/log: NewsAct onResume : IsForceKilled ?  true

操作:
按返回键

打印日志:
D/log: MainAct onRestoreInstanceState
D/log: MainAct onResume

显然,[Terminate Application] 按钮回收掉了App进程,重新代开应用,系统需要进行补偿,即恢复之前最后停留的页面NewsActivity。如果在NewsActivity页面中没有对集合变量 [news] 做缓存,因为不会经过MainActivity页面,[news] 将会造成空指针崩溃。

方案,对页面可能会造成这一崩溃现象的变量值进行缓存,以便于真的因为系统原因而造成的应用被回收重启恢复页面时不至于崩溃。

还有就是,尽可能的避免在页面中使用静态变量,如果需要使用到静态变量,则应该执行上面的方案,即进行值缓存。

如果应用中已经大量使用了静态变量,根本不想一个一个改(祖传代码改不得),还有最后一招。

就是判断强杀标志满足: isForceKilled == -1,然后主动重启:

public static void safeReLauncher() {

    BaseApplication application = BaseApplication.getApplication();
    Intent intent = application.getPackageManager().getLaunchIntentForPackage(application.getPackageName());
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    PendingIntent restartIntent = PendingIntent.getActivity(application.getApplicationContext(), 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK);

    //退出程序
    AlarmManager mgr = (AlarmManager) application.getSystemService(Context.ALARM_SERVICE);
    mgr.set(AlarmManager.RTC, 100, restartIntent); // 100毫秒后重启应用

    //结束进程之前可以把你程序的注销或者退出代码放在这段代码之前
    android.os.Process.killProcess(android.os.Process.myPid());
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值