安卓4.4.X:taskAffinity和放大器; launchmode与活动的生命周期 [英] android 4.4.X: taskAffinity & launchmode vs. Activity lifecycle

查看:201
本文介绍了安卓4.4.X:taskAffinity和放大器; launchmode与活动的生命周期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开发了一个简单的应用程序,这在演示功能的Andr​​oid 4.4.X设备,我注意到一些奇怪的行为。

I developed a simple application, which demostrates some strange behaviour on Android 4.4.X devices I noticed.

可以说,我想有两个主的活动,其中第一个说你好(通过启动HelloActivity)就会恢复每一秒的时间,而第二个具有安卓launchMode = singleTask机器人:taskAffinity =。MyAffinity定义。第二个是由第一个开始

Lets say I want to have 2 "main" activities, where the first says "Hello" (by starting 'HelloActivity') every second time it is resumed and the second one has android:launchMode="singleTask" android:taskAffinity=".MyAffinity" defined. Second one is started by the first one.

清单是pretty的简单:

Manifest is pretty simple:

<uses-sdk
    android:minSdkVersion="8"
    android:targetSdkVersion="14" />

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >

    <activity
        android:name="com.example.affinitylaunchmodebugtest.MainActivity"
        android:configChanges="keyboardHidden|orientation|screenSize"
        android:windowSoftInputMode="adjustResize">
        <intent-filter>
            <category android:name="android.intent.category.DEFAULT" />

            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <activity
        android:label="HELLO"
        android:name="com.example.affinitylaunchmodebugtest.HelloActivity"
        android:configChanges="keyboardHidden|orientation|screenSize">
    </activity>

    <activity
        android:label="AffinityTestActivity"
        android:name="com.example.affinitylaunchmodebugtest.AffinityTestActivity"
        android:configChanges="keyboardHidden|orientation|screenSize"
        android:launchMode="singleTask"
        android:taskAffinity=".MyAffinity">
    </activity>
</application>

MainActivity 开始AffinityTestActivity上按一下按钮,并记录其生命周期。它还启动HelloActivity就会恢复每一秒时间:

MainActivity starts AffinityTestActivity on button click and logs its lifecycle. It also starts HelloActivity every second time it is resumed:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        System.out.println(this+" onCreate");
        super.onCreate(savedInstanceState);

        Button b = new Button(MainActivity.this);
        b.setText("START AFFINITY TEST ACTIVITY");
        b.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                System.out.println(this+" starts "+AffinityTestActivity.class.getSimpleName());
                Intent intent = new Intent(MainActivity.this, AffinityTestActivity.class);
                startActivity(intent);
            }
        });
        setContentView(b);
    }

    private boolean skipHello = true;

    @Override
    protected void onResume() {
        System.out.println(this+" onResume");
        super.onResume();

        if (!skipHello) {
            System.out.println(this+" starts "+HelloActivity.class.getSimpleName());
            Intent intent = new Intent(MainActivity.this, HelloActivity.class);
            startActivity(intent);
            skipHello = true;
        } else {
            skipHello = false;
        }
    }

    @Override
    protected void onPause() {
        System.out.println(this+" onPause");
        super.onPause();
    }

    @Override
    protected void onDestroy() {
        System.out.println(this+" onDestroy");
        super.onDestroy();
    }

}

AffinityTestActivity 调用完成()上按一下按钮,并记录其生命周期:

AffinityTestActivity calls finish() on button click and logs its lifecycle:

public class AffinityTestActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        System.out.println(this+" onCreate");
        super.onCreate(savedInstanceState);

        Button b = new Button(AffinityTestActivity.this);
        b.setText("FINISH");
        b.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                System.out.println(this+" finishes");
                finish();
            }
        });
        setContentView(b);
    }

    @Override
    protected void onResume() {
        System.out.println(this+" onResume");
        super.onResume();
    }

    @Override
    protected void onPause() {
        System.out.println(this+" onPause");
        super.onPause();
    }

    @Override
    protected void onDestroy() {
        System.out.println(this+" onDestroy");
        super.onDestroy();
    }
}

HelloActivity 是一样的AffinityTestActivity实际上 - 它只有按钮调用完成()和printlns记录其生命周期

HelloActivity is the same as AffinityTestActivity in fact - it only has button to call finish() and printlns to log its lifecycle.

  1. 开始MainActivity。
  2. 开始AffinityTestActivity。
  3. 完成AffinityTestActivity(如AffinityTestActivity完成,MainActivity重新开始,HelloActivity开始)。
  4. 分析输出。

的Andr​​oid 4.4.2和4.4.3 :(在Nexus 7 II和三星Galaxy S5测试) 正如你所看到的,记录与HelloActivity的的onPause,这没有任何意义(HelloActivity在步骤3显示在顶部)结束。此外AffinityTestActivity不被破坏,并MainActivity没有被暂停。

Logs

Android 4.4.2 and 4.4.3: (tested on Nexus 7 II and Samsung Galaxy S5) As you can see, log ends with HelloActivity's onPause, which does not make sense (HelloActivity is displayed at top in step 3). Also AffinityTestActivity is not destroyed and MainActivity is not paused.

06-20 11:13:20.547: I/System.out(18650): com.example.affinitylaunchmodebugtest.MainActivity@41f17e50 onCreate
06-20 11:13:20.557: I/System.out(18650): com.example.affinitylaunchmodebugtest.MainActivity@41f17e50 onResume
06-20 11:13:25.371: I/System.out(18650): com.example.affinitylaunchmodebugtest.MainActivity$1@41f6e5c0 starts AffinityTestActivity
06-20 11:13:25.581: I/System.out(18650): com.example.affinitylaunchmodebugtest.MainActivity@41f17e50 onPause
06-20 11:13:25.591: I/System.out(18650): com.example.affinitylaunchmodebugtest.AffinityTestActivity@41f6a480 onCreate
06-20 11:13:25.611: I/System.out(18650): com.example.affinitylaunchmodebugtest.AffinityTestActivity@41f6a480 onResume
06-20 11:13:36.452: I/System.out(18650): com.example.affinitylaunchmodebugtest.AffinityTestActivity$1@41f1ede8 finishes
06-20 11:13:36.662: I/System.out(18650): com.example.affinitylaunchmodebugtest.AffinityTestActivity@41f6a480 onPause
06-20 11:13:36.682: I/System.out(18650): com.example.affinitylaunchmodebugtest.MainActivity@41f17e50 onResume
06-20 11:13:36.682: I/System.out(18650): com.example.affinitylaunchmodebugtest.MainActivity@41f17e50 starts HelloActivity
06-20 11:13:36.782: I/System.out(18650): com.example.affinitylaunchmodebugtest.HelloActivity@41f8dbb8 onCreate
06-20 11:13:36.802: I/System.out(18650): com.example.affinitylaunchmodebugtest.HelloActivity@41f8dbb8 onResume
06-20 11:13:36.852: I/System.out(18650): com.example.affinitylaunchmodebugtest.HelloActivity@41f8dbb8 onPause

较旧的Andr​​oid版本(&LT; 4.4.2,2.3.5上进行测试,4.1.2和4.2.1设备,4.0.3仿真器)按预期工作 - HelloActivity不经过暂停onResume和AffinityTestActivity被破坏:

Older Android versions (<4.4.2, tested on 2.3.5., 4.1.2 and 4.2.1 devices, 4.0.3 emulator) work as expected - HelloActivity is not paused after onResume and AffinityTestActivity is destroyed:

06-20 11:16:30.867: I/System.out(3296): com.example.affinitylaunchmodebugtest.MainActivity@40f998b0 onCreate
06-20 11:16:30.907: I/System.out(3296): com.example.affinitylaunchmodebugtest.MainActivity@40f998b0 onResume
06-20 11:16:34.157: I/System.out(3296): com.example.affinitylaunchmodebugtest.MainActivity$1@40f9b350 starts AffinityTestActivity
06-20 11:16:34.277: I/System.out(3296): com.example.affinitylaunchmodebugtest.MainActivity@40f998b0 onPause
06-20 11:16:34.297: I/System.out(3296): com.example.affinitylaunchmodebugtest.AffinityTestActivity@40fab810 onCreate
06-20 11:16:34.357: I/System.out(3296): com.example.affinitylaunchmodebugtest.AffinityTestActivity@40fab810 onResume
06-20 11:16:38.687: I/System.out(3296): com.example.affinitylaunchmodebugtest.AffinityTestActivity$1@40fad640 finishes
06-20 11:16:38.707: I/System.out(3296): com.example.affinitylaunchmodebugtest.AffinityTestActivity@40fab810 onPause
06-20 11:16:38.717: I/System.out(3296): com.example.affinitylaunchmodebugtest.MainActivity@40f998b0 onResume
06-20 11:16:38.717: I/System.out(3296): com.example.affinitylaunchmodebugtest.MainActivity@40f998b0 starts HelloActivity
06-20 11:16:38.747: I/System.out(3296): com.example.affinitylaunchmodebugtest.MainActivity@40f998b0 onPause
06-20 11:16:38.777: I/System.out(3296): com.example.affinitylaunchmodebugtest.HelloActivity@40fbdd48 onCreate
06-20 11:16:38.827: I/System.out(3296): com.example.affinitylaunchmodebugtest.HelloActivity@40fbdd48 onResume
06-20 11:16:39.877: I/System.out(3296): com.example.affinitylaunchmodebugtest.AffinityTestActivity@40fab810 onDestroy

我的问题(S)

  • 为什么我的HelloActivity暂停上启动并显示在顶部?
  • 在右侧的Andr​​oid 4.4.X设备
  • 如何避免它,并强制应用程序有正常的活动周期,因为年长的Andr​​oid版本(小于4.4.2)?做
  • My Question(s)

    • Why is my HelloActivity paused on Android 4.4.X devices right after it is started and displayed at top?
    • How can I avoid it and force the application to have "normal" activity lifecycle, as older Android versions (<4.4.2) do?
    • 我开发的应用程序,这是更为复杂,并与活动的生命周期,这种行为违反了我的应用程序的功能。

      I develop application, which is much more complex and works with lifecycle of its activities and this behaviour is violating my application's functionality.

      非常感谢你!

      推荐答案

      我已经创建了一个基于你所提供的code一个项目,我能够在我自己的Nexus 7,重新您的问题虽然我不'T有一个具体的,对你的学术答案,我的最好的解释是这样的:

      I've created a project based on the code you provided, and I was able to recreate your issue on my own Nexus 7. While I don't have a concrete, academic answer for you, my best explanation is the following:

      1)MainActivity起动

      1) MainActivity is started

      2)单击按钮。 AffinityTestActivity开始在一个新的任务。

      2) Button clicked. AffinityTestActivity is started in a new task.

      3)单击按钮。 AffinityTestActivity完成。

      3) Button clicked. AffinityTestActivity finishes.

      4)MainActivity内的旧任务恢复。

      4) MainActivity resumes within the old task.

      5)在MainActivity的onResume,意图为HelloActivity称为同一任务中。

      5) In MainActivity's onResume, the intent for HelloActivity is called within the same task.

      6)神秘的部件,它是我的理论一些调整后:把旧的任务推到前台的某些部分继续onResume通话过程中与MainActivity,老任务的根源,进行互动。这种相互作用导致被触发的HelloActivity的的onPause方法(可能不是由操作系统开发商意)。虽然这还不是最令人满意的答案(因为我与OS级调度code和时序问题的经验有限),我的实验指出,类似的规定。我的第一个线索,这种干扰是这种频繁的错误出现在logcat中:

      6) The mysterious part which is my theory after a bit of tinkering: Some part of bringing the old task to the foreground continues to interact with MainActivity, the root of the old task, during its onResume call. This interaction causes the HelloActivity's onPause method to be triggered (probably not intended by the OS developers). While this isn't the most satisfying answer (given my limited experience with OS-level scheduling code and timing issues), my experiments point to something along those lines. My first clue to this interference was this frequent error seen in logcat:

      06-24 11:06:28.015  27200-27200/com.stackoverflow I/System.out﹕ com.stackoverflow.MainActivity@64e05830 onPause
      06-24 11:06:28.055  27200-27200/com.stackoverflow I/System.out﹕ com.stackoverflow.AffinityTestActivity@64e22fc0 onCreate
      06-24 11:06:28.075  27200-27200/com.stackoverflow I/System.out﹕ com.stackoverflow.AffinityTestActivity@64e22fc0 onResume
      06-24 11:06:28.175      665-685/? I/ActivityManager﹕ Displayed com.stackoverflow/.AffinityTestActivity: +163ms
      06-24 11:06:29.997  27200-27200/com.stackoverflow I/System.out﹕ com.stackoverflow.AffinityTestActivity$1@64e24bf8 finishes
      06-24 11:06:30.007  27200-27200/com.stackoverflow I/System.out﹕ com.stackoverflow.AffinityTestActivity@64e22fc0 onPause
      06-24 11:06:30.027  27200-27200/com.stackoverflow I/System.out﹕ com.stackoverflow.MainActivity@64e05830 onResume
      06-24 11:06:30.027  27200-27200/com.stackoverflow I/System.out﹕ com.stackoverflow.MainActivity@64e05830 starts HelloActivity
      06-24 11:06:30.027     665-6346/? I/ActivityManager﹕ START u0 {cmp=com.stackoverflow/.HelloActivity} from pid 27200
      06-24 11:06:30.117  27200-27200/com.stackoverflow I/System.out﹕ com.stackoverflow.HelloActivity@64e33b18 onCreate
      06-24 11:06:30.127  27200-27200/com.stackoverflow I/System.out﹕ com.stackoverflow.HelloActivity@64e33b18 onResume
      06-24 11:06:30.137  27200-27200/com.stackoverflow I/System.out﹕ com.stackoverflow.HelloActivity@64e33b18 onPause
      06-24 11:06:30.287      665-685/? I/ActivityManager﹕ Displayed com.stackoverflow/.HelloActivity: +182ms
      06-24 11:06:32.389  27200-27200/com.stackoverflow I/System.out﹕ com.stackoverflow.HelloActivity$1@64e356b0 finishes
      06-24 11:06:32.389  27200-27200/com.stackoverflow I/System.out﹕ com.stackoverflow.HelloActivity@64e33b18 onDestroy
      06-24 11:06:32.399  27200-27200/com.stackoverflow I/System.out﹕ com.stackoverflow.MainActivity@64e05830 onPause
      06-24 11:06:32.399  27200-27200/com.stackoverflow E/ActivityThread﹕ Performing pause of activity that is not resumed: {com.stackoverflow/com.stackoverflow.MainActivity}
      java.lang.RuntimeException: Performing pause of activity that is not resumed: {com.stackoverflow/com.stackoverflow.MainActivity}
      at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3015)
      at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3003)
      at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:2981)
      at android.app.ActivityThread.access$1000(ActivityThread.java:135)
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1207)
      at android.os.Handler.dispatchMessage(Handler.java:102)
      at android.os.Looper.loop(Looper.java:136)
      at android.app.ActivityThread.main(ActivityThread.java:5001)
      at java.lang.reflect.Method.invoke(Native Method)
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
      06-24 11:06:32.409  27200-27200/com.stackoverflow I/System.out﹕ com.stackoverflow.MainActivity@64e05830 onResume
      06-24 11:06:32.769  27200-27200/com.stackoverflow I/System.out﹕ com.stackoverflow.AffinityTestActivity@64e22fc0 onDestroy
      

      正如你所看到的,MainActivity的方法的onPause甚至没有叫HelloActivity结束之后。这是不对的任一。对我来说,表明开始在onResume的活动,而该任务被带到前台会引起一些意想不到的冲突中的生命周期。

      As you can see, MainActivity's onPause method wasn't even called until after HelloActivity was finished. That's not right either. That, to me, shows that starting an activity within onResume while the task is being brought to the foreground is causing some unintended conflicts in the lifecycle.

      要看看我给活动/任务,第二个完成任何看不见的处理发生了什么事,我用了一个处理程序来调用MainActivity的HelloActivity意图:

      To see what happened if I gave the activity/task a second to complete any unseen processing, I used a handler to call the HelloActivity intent in MainActivity:

       @Override
      protected void onResume() {
          System.out.println(this + " onResume");
          super.onResume();
      
          if (!skipHello) {
              System.out.println(this+" starts "+HelloActivity.class.getSimpleName());
      
              mHandler.postDelayed(new Runnable() {
                  @Override
                  public void run() {
                      Intent intent = new Intent(MainActivity.this, HelloActivity.class);
                      startActivity(intent);
                  }
              }, 1000);
      
              skipHello = true;
          } else {
              skipHello = false;
          }
      }
      

      这导致了更好的性能。 HelloActivity充当应该和在onPause不叫。显然,这是不理想的工作code,但它表明,简单地把执行时间向前第二个解决了这一问题。更多的证据的任务中内部调度的冲突。

      This resulted in much better behavior. HelloActivity acted as it should, and onPause wasn't called. Obviously this isn't ideal for working code, but it shows that simply moving execution time forward by a second fixed the problem. More evidence of internal scheduling conflict within the task.

      接下来,我试着给HelloActivity了自己的任务,以及:

      Next, I tried giving HelloActivity its own task as well:

      <activity
          android:label="HELLO"
          android:name="com.stackoverflow.HelloActivity"
          android:configChanges="keyboardHidden|orientation|screenSize"
          android:launchMode="singleTask"
          android:taskAffinity=".DifferentTask">
      </activity>
      

      (根据记录,这种配置并没有太大的意义,但我认为这是反映在你的,有一个更合乎逻辑的目的,真正的项目的情况。)

      (For the record, this configuration doesn't make much sense, but I assume it's reflecting a scenario in your real project that has a more logical purpose.)

      在这种情况下,一切工作正常。 HelloActivity的生命周期不会干扰MainActivity的生命周期。然而,现在有自己的任务的开销和运行活动为 singleTask (打主页按钮,并重新打开应用程序,将带你到MainActivity随行的问题,留下HelloActivity人迹罕至在其新的任务,即使是在关闭应用程序之前查看的最后一项活动)。

      Under this scenario, everything works fine. HelloActivity's lifecycle does not interfere with MainActivity's lifecycle. However, it now has the overhead of its own task and the accompanying problems of running an activity as singleTask (hitting the "Home" button and reopening the app will take you to MainActivity, leaving HelloActivity inaccessible in its new task even though it was the last activity viewed before closing the app).

      我的最好的建议是要找到一个方法来避免此特定情形。 :)现在看来似乎是更高版本的Andr​​oid中的一个bug,虽然是一个奇怪的边缘情况。如果这不是一种选择,你可以追求我用得到它周围的途径之一。我已经尝试了几个其他的东西,但它是很难解决的调度控制在我们的掌握之外的操作系统级别的事实。

      My best recommendation would be to find a way to avoid this particular scenario. :) It seems like it's a bug within later versions of Android, albeit a strange edge case. If that's not an option, you could pursue one of the routes I used to get around it. I've tried a couple other things, but it's difficult to get around the fact that the scheduling is controlled at an OS level outside our grasp.

      对不起,我不能给你一个更深入的答案,但这是我的一切,现在!

      Sorry that I couldn't get you a more in-depth answer, but that's all I've got for now!

      这篇关于安卓4.4.X:taskAffinity和放大器; launchmode与活动的生命周期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆