【问题标题】:OnCreate method keeps getting called repeatedlyOnCreate 方法不断被重复调用
【发布时间】:2013-01-16 05:58:22
【问题描述】:

更新:感谢大家尝试帮助我解决这个错误。我仍然不确定原因,我能够回滚到之前的提交并从那里继续开发。这个先前的提交确实显示了相同的错误,但是在我注释掉button.performClick() 之后它就消失了。奇怪的是,这不适用于最近的提交。

我仍然不明白这个错误,如果能提供更多帮助来帮助确定根本原因,我将不胜感激。我最大的恐惧是无意中重新引入它。


我遇到了我见过的最疯狂的错误。

OnCreate 方法被一遍又一遍地调用,冻结了我的应用程序并给了我轻微的闪烁。唯一的解决方案是退出到主屏幕并从设置菜单中强制退出应用程序。

以下是详细情况:

  1. 应用程序启动(主活动)
  2. 主 Activity 调用第二个 Activity
  3. 第二个 Activity 调用 onCreate,正常设置
  4. Second Activity 随机决定退出 onCreate
  5. 再次调用第二个活动的 onCreate。它永远不会返回到 Main Activity。

我已经运行了一个调试器,看来第二个活动成功完成了 onComplete/onResume 序列,然后决定退出并重新启动。

以前有人听说过这种行为吗?

我没有注意到任何异常被抛出。此外,在调试过程中,我确实继续检查了您认为无提示失败的位置。 (这是在我用打印语句乱扔它之前的旧代码)

更新:当试图停止进程时,我必须打开飞行模式。这意味着它与这个代码块有关(第二个活动)

else if (Network.haveNetworkConnection(Login.getContext()) && Login.checkClientId())
        {...}

在没有网络的情况下,会命中else语句,不显示此行为。

代码:

主 Activity 的 onResume(),我称之为第二个 Activity:

    @Override
    public void onResume()
    {
        super.onResume();

        //Check If logged in, else go to login page
        Login.setContext(getApplicationContext());

        //Reset Notification Number
        GCMIntentService.cancelNotifications();

        /** GO TO LOGIN **/
        if(!Login.isLoggedIn())
        {
            //If user is not logged in, open login page
            System.out.println("RESUMING MAIN AND STARTING LOGIN INTENT");
            Intent intent = new Intent(ActivityMain.this, ActivityLogin.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);

        } else
        {
            Login.setupStuffOnce();
            Event.pullEvents(); //Get New Events

            //Update ListView
            updateMainFeed();
        }


    }

这是第二个活动:

public class ActivityLogin extends Activity
{

    private String postData;
    //private Context c;
    //final Timer timer = new Timer();

    //Facebook Stuff
    private Facebook facebook = new Facebook(Config.FBAPPID);
    private AsyncFacebookRunner mAsyncRunner = new AsyncFacebookRunner(facebook);

    //Layout Stuff
    EditText username, password;
    Button loginButton, signupButton;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        // Open Database
        Login.setContext(getApplicationContext());
        Database.open(getApplicationContext());
    }

    /*
     * @Override public void onPause() { s }
     */
    @Override
    public void onResume()
    {
        super.onResume();

        // shouldn't put here but oh well
        init();

        //If coming from ActivitySignup
        if(Transfer.username != null)
        {
            username.setText(Transfer.username);
            password.setText(Transfer.password);
            Transfer.password = null;
            Transfer.username = null;
            loginButton.performClick();
        }

    }

    public void init()
    {

        Login.getUserLoggedIn();
        if (Login.isLoggedIn())
        {
            //Do Any Additional Setup
            Login.setupStuffOnce();

            // If user is logged in, open main
            Intent intent = new Intent(ActivityLogin.this, ActivityMain.class);
            //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);

        } else if (Network.haveNetworkConnection(Login.getContext()) && Login.checkClientId())
        {
            // Else, Make User Login
            // Inflate Login and Present Website
            String clientid = Login.getClientId();
            System.out.println("clientid:" + clientid);
            //System.exit(0);
            postData =  "mobile=1&client_id="+Login.getClientId();



            // Inflate the view
            setContentView(R.layout.activitylogin3);

            username = (EditText) findViewById(R.id.username);
            password = (EditText) findViewById(R.id.password);



            //Inflate the Button
            loginButton = (Button) findViewById(R.id.loginButton);
            signupButton = (Button) findViewById(R.id.signupButton);

            signupButton.setOnClickListener(new View.OnClickListener()
            {

                @Override
                public void onClick(View v)
                {
                    Intent intent = new Intent(ActivityLogin.this, ActivitySignup.class);
                    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
                    startActivity(intent);

                }
            });

            loginButton.setOnClickListener(new View.OnClickListener() {
                  public void onClick(View view) {

                     int res = Login.sendLogin(username.getText().toString(), password.getText().toString());

                     if(res == 202)
                     {
                         //Login Successful

                         //Check if facebooked.
                         if(Login.isFacebooked())
                         {
                             //Just go to main
                             Intent intent = new Intent(ActivityLogin.this, ActivityMain.class);
                             //Are these flags necessary?
                             //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
                             startActivity(intent);
                         } else
                         {
                             //Go to facebook login page
                             //Intent intent = new Intent(ActivityLogin.this, ActivityFBLogin.class);
                             //startActivity(intent);

                             //Login via Facebook
                             doFacebook();
                         }

                     } else
                     {
                         System.out.println("Login Failed: "+res);
                         if(res == 405)
                         {
                             Toast.makeText(getApplicationContext(), "Incorrect Username/Password", Toast.LENGTH_SHORT).show();
                             password.setText("");
                         }
                         else
                             Toast.makeText(getApplicationContext(), "Network Error", Toast.LENGTH_SHORT).show(); //Not entirely true in all cases i think

                     }



                      /*Login.getUserLoggedIn();
                        if(Login.isLoggedIn())
                        {
                            Intent intent = new Intent(ActivityLogin.this, ActivityMain.class);
                            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
                            startActivity(intent);
                        } else {
                            Toast.makeText(getApplicationContext(), "Please Login Above", Toast.LENGTH_SHORT).show();
                        }*/
                  }
                });



        } else
        {
            // Not Logged In and No Internet Access

            setContentView(R.layout.activitylogintext);

            EditText text = (EditText) findViewById(R.id.text);
            text.setText("No Internet Connection Detected\n requires internet to login");

            Button button = (Button) findViewById(R.id.refreshButton);

            button.setOnClickListener(new View.OnClickListener() {
                  public void onClick(View view) {
                        //Login.getUserLoggedIn();
                        if(Network.haveNetworkConnection(Login.getContext()))
                        {
                            Intent intent = new Intent(ActivityLogin.this, ActivityLogin.class);
                            //intent.setFlags();
                            startActivity(intent);
                        } else {
                            Toast.makeText(getApplicationContext(), "No Internet Access Detected", Toast.LENGTH_SHORT).show();
                        }
                  }
                });

        }

    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        facebook.authorizeCallback(requestCode, resultCode, data);
    }

    public void doFacebook()
    {
         facebook.authorize(this, Config.facebookPermissions, new DialogListener() {
                @Override
                public void onComplete(Bundle values) {
                     /*SharedPreferences.Editor editor = state.edit();
                     editor.putString("access_token", facebook.getAccessToken());
                     editor.putLong("access_expires", facebook.getAccessExpires());
                     editor.commit();
                        */
                     //Input into database
                     Login.saveAccessToken(facebook.getAccessToken());
                     Login.setFB(facebook.getAccessToken());
                     //Login.sendAccessToken(facebook.getAccessToken());

                     //Intent into Main Activity
                     Intent intent = new Intent(ActivityLogin.this, ActivityMain.class);
                    //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(intent);
                }

                @Override
                public void onFacebookError(FacebookError error) {
                    Toast.makeText(getApplicationContext(), "Error: "+error.getErrorType(), Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onError(DialogError e) {
                    Toast.makeText(getApplicationContext(), "Error: "+e.getMessage(), Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onCancel() {}
            });
    }

    public boolean checkForUserID(Context c)
    {
        try{
            String res = Network.getUrl("www.website.com/mobile.php?got_user=1&client_id="+Login.getClientId());
            JSONObject json = JSON.constructObject(res);
            if(JSON.handleCode(json))
            {
                if(json.getString("type").equals("userid"))
                {
                    Login.setLogin(json.getString("data"));
                    return true;
                }
            }
        } catch(Exception e)
        {
            //Silent Fail
        }
        return false;
    }


}

【问题讨论】:

  • 我认为你必须发布一些代码。至少从主活动开始活动。以及第二个活动的 onCreate()
  • 不会随机决定退出;我只知道可能发生的三件事 1)异常(应该在 logcat 中)2)正常返回(例如 return 或 run-off-end)或 3)进程被终止(不应该发生)。
  • 话虽如此,我也听说过将 negative 值传递给 startActivityForResult 或在 onCreate 中调用 finish 引起的问题(这不一定会改变任何退出点,但可能导致其他交互)
  • 我没有发现任何异常。我将很快发布代码
  • 我的代码盲投赞成——您正在从第二个活动的onCreate 调用第二个活动

标签: android oncreate


【解决方案1】:

我相信,如果您在致电SecondActivity 后完成您的MainActivity,问题将会得到解决。问题可能是当您恢复MainActivity 时,onResume 事件会立即触发。这是因为MainActivity 可能在后台被销毁并重新创建。另一种解决方案是使用onSaveInstanceState 保存您的活动状态。请参阅here 了解更多信息。

【讨论】:

  • 我很快就会对此进行测试。但是我认为它根本不会返回 MainActivity。
  • 不幸的是,在 main 中调用 finish() 并没有解决问题
【解决方案2】:

在您的活动中检查此代码:

    Button button = (Button) findViewById(R.id.refreshButton);
    button.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {

                    if(Network.haveNetworkConnection(Login.getContext()))
                    {
                        Intent intent = new Intent(ActivityLogin.this, ActivityLogin.class);
                        //intent.setFlags();
                        startActivity(intent);
                    } else {
                        Toast.makeText(getApplicationContext(), "No Internet Access Detected", Toast.LENGTH_SHORT).show();
                    }
              }
            });

在这里您调用的是 ActivityLogin 本身。 这就是为什么onCreate() 被一次又一次地调用的原因。

【讨论】:

  • 我将重新检查此部分。但是,由于这是在按钮的 onClick() 方法中,我不认为这是问题所在。这样做的原因是它会重新启动 Activity 以检查 Internet 连接并在需要时更新屏幕。
  • @TheRealKingK,好的。并在第一个活动中检查 if(!Login.isLoggedIn()) 案例。它还将重新启动 ActivityLogin。
  • 我正在检查按钮。但是,它确实成功完成了 onCreate 和 onResume 方法。这应该排除这个问题,因为它位于 onCreate.
  • @TheRealKingK loginButton.performClick(); - 这不会触发onClick吗? (我认为这个解释是有道理的。开始注释掉代码;例如performClick,直到找到原因。)
  • 有一些失败的案例,因此递归调用
【解决方案3】:

我曾经遇到过类似的问题。出现问题是因为我没有在<activity> 标记的android:configChanges 属性中声明配置更改(因此它一直在重新创建自己)。

例如,如果您手动更改语言环境,则需要将locale 添加到android:configChanges

【讨论】:

  • 我真的希望是这样。但是在测试了我能捕捉到的每一个可能的情况之后,我不得不得出结论,事实并非如此。但是感谢您的信息
  • 只是为了确保:您是否更改了语言环境?如果是,您是否在 4.2 上进行测试?如果是,除了语言环境之外,您还必须在 configChanges 中添加 layoutDirection(这就是我的问题)!
  • 我无法添加 layoutDirection,可能是因为它是在 API 17 中添加的。它似乎没有将该标志识别为有效。我正在测试 API 8 (2.2)。
【解决方案4】:

在我看来,如果 Login 没有在活动之间正确共享,那么在我看来,这里很有可能在这里无限循环,导致 Login.isLoggedIn()ActivityLogin 中返回 true,但在 ActivityMain 中返回 false

一些关键因素是您的Login 对象所在的位置,它是静态的,它是如何在活动之间引用的? ActivityLogin 处于活动状态时,ActivityMain 完全有可能被销毁;将登录数据存储在SharedPreferences 或数据库中,或者以其他方式将其持久化很重要。 isLoggedIn() 如何解析(确定其return 值?)

建议 1:考虑使用单例模式(如果您还没有的话。) 建议 2:虽然不鼓励,但您可以将 Login 存储在 Application 级别。 建议 3:您可以尝试使用 Intent.FLAG_ACTIVITY_SINGLE_TOP 来减少创建新 ActivityMain 的可能性 - 这可能无法访问 Login,这再次取决于您的存储方式。

ActivityMain

onResume() {
    if(!Login.isLoggedIn()) {
        /* Not logged in, launch ActivityLogin! */
        Intent intent = new Intent(ActivityMain.this, ActivityLogin.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);

活动登录

onResume() { /* ... */ init(); }

init() {
    Login.getUserLoggedIn();
    if (Login.isLoggedIn()) {
        /* Internet - launch ActivityMain! */
        Intent intent = new Intent(ActivityLogin.this, ActivityMain.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); // <--- suggested addition
        startActivity(intent);
    else if (Network.haveNetworkConnection(Login.getContext()) && Login.checkClientId()) {
        /* No internet, the user was unable to login. */
    }

【讨论】:

    【解决方案5】:

    我认为您的主要问题在于您的 onResume 函数,因为它每次返回视图时都会被调用(例如:您开始第二个活动,完成它,再次调用主要活动 onResume。如果您完成了第二个活动(或由于某种原因它悄悄地崩溃了)你将回到你的 mainActivity 并调用 onResume (这将重新开始循环)。

    现在我不知道你是否正在以某种方式完成活动 2,但我会检查一下。

    编辑: 另外我会在这里放一些logcats

    if (Login.isLoggedIn())
    {
          //Do Any Additional Setup
          Login.setupStuffOnce();
    
          // If user is logged in, open main
          Intent intent = new Intent(ActivityLogin.this, ActivityMain.class);
          //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
          Log.i("Some Tag", "Starting Main Activity From Activity 2");
          startActivity(intent);
    
    }
    

    上面添加的 log.i 会让你知道这是否是错误发生的地方,你可以从那里开始。

    【讨论】:

    • 正如我之前提到的,它永远不会返回到 Main.onResume()。我已经广泛检查了这种行为。
    【解决方案6】:

    我遇到了类似的问题,即始终重新创建活动。重新安装应用程序没有帮助,但重新启动手机就可以了。

    【讨论】:

    • 哇!我很高兴人们还在看我的帖子!不幸的是,我确实尝试重新启动手机,但没有成功。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多