Java 当活动在其异步任务运行时被销毁时,内存中会发生什么情况?

Java 当活动在其异步任务运行时被销毁时,内存中会发生什么情况?,java,android,android-asynctask,garbage-collection,Java,Android,Android Asynctask,Garbage Collection,我一直在玩我创建的应用程序 活动A(第一个活动)有一个执行异步任务的按钮。此AsyncTask的doInBackground()对活动A中的选定值执行计算,其onPostExecute()启动活动B 我点击按钮,然后在活动B可以开始之前,我按下后退以销毁活动A 应用程序关闭,然后重新启动,活动B中填充了来自AsyncTask的计算 解释当屏幕旋转时线程的内存泄漏,我在这里用AsyncTask和back按钮应用这些经验教训。然而,我还是有点困惑 对某个活动进行回击会破坏它 我的asynctask正

我一直在玩我创建的应用程序

  • 活动A(第一个活动)有一个执行异步任务的按钮。此AsyncTask的doInBackground()对活动A中的选定值执行计算,其onPostExecute()启动活动B

  • 我点击按钮,然后在活动B可以开始之前,我按下后退以销毁活动A

  • 应用程序关闭,然后重新启动,活动B中填充了来自AsyncTask的计算

  • 解释当屏幕旋转时线程的内存泄漏,我在这里用AsyncTask和back按钮应用这些经验教训。然而,我还是有点困惑

  • 对某个活动进行回击会破坏它

  • 我的asynctask正在一个已销毁的活动上运行,应该抛出一个NPE,因为它正在访问该活动中的列表元素

  • 但事实并非如此。那么毁灭到底意味着什么呢?我认为这意味着活动A引用及其视图层次结构将设置为null,以允许垃圾收集器在某个时候将其清除并回收内存。博客上说没有,因此内存泄漏

  • 等等,活动A没有被摧毁?但我看到它消失了

    到目前为止,这是一个概念性问题,而不是代码问题,但根据要求:

    private class MyAsyncTask extends AsyncTask<ArrayList<Train>, Void, Void> {
    
        protected void onPreExecute() {
            // Runs on the UI thread before doInBackground
            spinWait.setVisibility(ProgressBar.VISIBLE);
            waitMsg.setText("Calculating Schedules....");
    
            spinWait.bringToFront();
            waitMsg.bringToFront();
        }
    
    
        @Override
        protected Void doInBackground(ArrayList<Train>... lolTrains) {
    
            try {
                calcSchedules(lolTrains[0]);
            } catch (Exception e) {
                Log.d("DEBUG", "Calculating schedules failed, " + e.getMessage());
            }
            return null;
        }
    
    
        @Override
        protected void onPostExecute(Void v) {
            // This method is executed in the UIThread
            spinWait.setVisibility(View.GONE);
            waitMsg.setVisibility(View.GONE);
    
            // if schedules is empty, show error dialog
            if (schedules.size() == 0) {
                // show msg, etc
            } else {
                Intent i = new Intent(getBaseContext(), ResultsActivity.class);
                i.putExtra("results", schedules);
                startActivity(i);
            }
        }
    }
    
    public void MethodInActivityA(View v) {
        new MyAsyncTask().execute(memberVarInActivityA);
    }
    
    私有类MyAsyncTask扩展了AsyncTask{
    受保护的void onPreExecute(){
    //在doInBackground之前在UI线程上运行
    设置可见性(ProgressBar.VISIBLE);
    waitMsg.setText(“计算时间表…”);
    spinWait.bringToFront();
    waitMsg.bringToFront();
    }
    @凌驾
    受保护的空doInBackground(ArrayList…lolTrains){
    试一试{
    calcSchedules(lolTrains[0]);
    }捕获(例外e){
    Log.d(“调试”,“计算计划失败,”+e.getMessage());
    }
    返回null;
    }
    @凌驾
    受保护的void onPostExecute(void v){
    //此方法在UIThread中执行
    spinWait.setVisibility(View.GONE);
    waitMsg.setVisibility(View.GONE);
    //如果计划为空,则显示错误对话框
    如果(schedules.size()==0){
    //显示味精等
    }否则{
    Intent i=新的Intent(getBaseContext(),ResultsActivity.class);
    i、 额外费用(“结果”,附表);
    星触觉(i);
    }
    }
    }
    公共空间(视图五){
    新建MyAsyncTask().execute(MemberVariaActivitya);
    }
    
    当您销毁活动时,您并没有销毁AsyncTask(这基本上是一种
    线程)
    ,您可以尝试这样做

    asyncTask.cancel(true);
    
    在您的
    ondestory()上方法


    希望这对您的
    onPostExecute()
    有所帮助,当启动新的活动调用
    finsih()
    后接
    startActivity(i)
    。这个
    finish()
    内部调用
    onDestroy
    。这里您需要手动清除Asynctask,因为Asynctask是活动的内部类。即使activity被销毁,这个内部类也持有activity的引用。您需要通过
    asyncTask.cancel()

    手动清除引用活动销毁是Android的概念。这意味着活动实例将永远不会再向用户显示,因此最终将任由GC摆布,而不会发生这种情况immediately@Machinarius:因此事件顺序为活动A消失但内存仍然存在,因为AsyncTask引用了它,然后出现活动B,那么活动A内存会被垃圾回收,因为AsyncTask是通过活动A完成的?类似的,问题是您的回调在活动A上触发,这意味着在最佳情况下数据会被浪费,并且您的应用程序会崩溃,因为您试图在最坏的情况下更新无效的ui。您能澄清一下您的意思吗“最佳和最坏情况”?我不认为我的应用程序崩溃是因为我没有得到“不幸的是,appname已停止”的提示“错误对话框。如果你不使用线程中的数据来更新你的用户界面,那么一切都会按你的方式进行-这只是内存泄漏-愉快地掩盖问题。”。如果这样做,可能会出现异常,因为您试图更新已销毁活动的UI。