IntentService防止活动毁坏(IntentService prevents activit

2019-09-28 19:38发布

据我知道,当我旋转屏幕,该活动被破坏并重新创建。 在下列情况下,它看起来像这样的情况并非总是如此。 所以,问题是:是否真的破坏了? 我是内存泄漏出于某种原因? 如果它不被破坏,它在同一个线程中新创建的活动上运行?

该方案是一个启动IntentService的“垂直”的活动,该服务需要5秒才能完成,并且采用了ResultReceiver发回的结果。 在这5秒,屏幕被旋转,一个新的“水平”活动被创建。 结果回来的“垂直”的活动,而不是新的“水平”。 因此,“垂直”的活动不被破坏?

我创建了一个项目来证明这一点。 这里谈到的代码。

首先,活动布局的XML。 只是两个按钮。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Show value of variable" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start IntentService" />

</LinearLayout>

在那之后,我们IntentService

public class SomeService extends IntentService {

    public SomeService(){
        super("SomeService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        ResultReceiver receiver = (ResultReceiver) intent.getParcelableExtra("receiver");

        long t0, t1;
        t0 = System.currentTimeMillis();
        do {
            t1 = System.currentTimeMillis();
        } while (t1-t0 < 5000);

        receiver.send(0, null);
    }
}

最后活动

public class TestActivityDestructionActivity extends Activity {

    private int mTestVar = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        if (savedInstanceState != null){
            mTestVar = savedInstanceState.getInt("tv");
        }

        mTestVar++;

        Button b1 = (Button) findViewById(R.id.button1);
        b1.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Toast.makeText(TestActivityDestructionActivity.this, "Value: " + mTestVar, Toast.LENGTH_SHORT).show();
            }
        });

        Button b2 = (Button) findViewById(R.id.button2);
        b2.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Intent intent = new Intent(TestActivityDestructionActivity.this, SomeService.class);
                intent.putExtra("receiver", new SomeReceiver(new Handler()));
                startService(intent);
                Toast.makeText(TestActivityDestructionActivity.this, "IntentService started", Toast.LENGTH_SHORT).show();
            }
        });

    }

    private class SomeReceiver extends ResultReceiver{
        public SomeReceiver(Handler handler) {
            super(handler);
        }

        @Override
        protected void onReceiveResult(int resultCode, Bundle resultData) {
            super.onReceiveResult(resultCode, resultData);
            Toast.makeText(TestActivityDestructionActivity.this, "Receiver value: " + mTestVar, Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("tv", mTestVar);
    }
}

当活动开始的第一次,mTestVar为0,它的onCreate是inceased 1。当活动被破坏,它保存的价值。 接下来的活动加载它,它增加了2,依此类推。

按照这些步骤:

  1. 单击Button:mTestVar是1
  2. 点击Button2的:服务得到启动
  3. 旋转屏幕5秒消逝之前
  4. 单击Button:mTestVar是2(的onCreate被称为)
  5. 等待5秒消逝:mTestVar被示出为仍然具有1值

据我所看到的,这意味着第一个活动都没有被破坏。 我这么想吗?

谢谢!

编辑

看到这个问题的答案后,我用MAT和堆转储,并发现第一个活动是永远不会被垃圾收集,即使该服务的时间了,垃圾收集,并没有对活动没有引用了。 我不知道为什么。

但是,如果从来没有创建了接收器和从未传递给服务,没有内存泄漏。 如预期的第一项活动被破坏。 我们没有理由不给,反正。

Answer 1:

通过在代码中的断点调试器中运行它,并选中“本”在ResultReceiver的ID。 它保持的“这一”本地副本,它指向先前的活动,其中int mTestVar == 1。当前活跃的活动是一个完全不同的对象,有它自己的mTestVar == 2的副本这是内存泄漏。

为了更简明地回答你的问题:Android的“破坏”你们的活动,但你在你的回调保持活动的引用防止它被垃圾收集。 如果你想要的东西,以“活”在多项活动中,你应该使用服务来存储状态(记住服务不是一个单独的线程,不应该像一个使用)。

旁注:当检查变量和通用的日志记录,最好使用Log.v / E / I等。您可以在与亚行logcat MyTag的命令行进行筛选:V *:S或使用内置到Eclipse的logcat的。



文章来源: IntentService prevents activity from destroying