在Android上重新启动活动

在Android上重新启动活动,android,rotation,android-activity,Android,Rotation,Android Activity,在我的Android应用程序中,当我旋转设备(滑出键盘)时,我的活动将重新启动(onCreate)。现在,这可能是应该的,但我在onCreate方法中进行了很多初始设置,因此我需要: 将所有初始设置放在另一个功能中,这样就不会在设备旋转或 使创建时不再调用onCreate,布局只是调整或更改 将应用程序限制为仅纵向,以便不调用onCreate 您描述的是默认行为。您必须通过添加以下内容来检测和处理这些事件: android:configChanges 添加到清单,然后添加要处理的更改。因此,对

在我的Android应用程序中,当我旋转设备(滑出键盘)时,我的
活动将重新启动(
onCreate
)。现在,这可能是应该的,但我在
onCreate
方法中进行了很多初始设置,因此我需要:

  • 将所有初始设置放在另一个功能中,这样就不会在设备旋转或
  • 使创建时不再调用
    onCreate
    ,布局只是调整或更改
  • 将应用程序限制为仅纵向,以便不调用
    onCreate

  • 您描述的是默认行为。您必须通过添加以下内容来检测和处理这些事件:

    android:configChanges
    
    添加到清单,然后添加要处理的更改。因此,对于方向,您将使用:

    android:configChanges="orientation"
    
    android:configChanges="keyboardHidden"
    
    对于要打开或关闭的键盘,您将使用:

    android:configChanges="orientation"
    
    android:configChanges="keyboardHidden"
    
    如果要处理这两个问题,可以使用管道命令将它们分开,如:

    android:configChanges="keyboardHidden|orientation"
    
    这将在您调用的任何活动中触发onConfigurationChanged方法。如果重写该方法,则可以传入新值


    希望这有帮助。

    使用应用程序类

    根据您在初始化过程中所做的,您可以考虑创建一个新的类,该类扩展了<代码>应用程序>代码>,并将初始化代码移动到该类中重写的<代码> OnCudio< /Cult>方法。

    public class MyApplicationClass extends Application {
      @Override
      public void onCreate() {
        super.onCreate();
        // TODO Put your application initialization code here.
      }
    }
    
    application类中的
    onCreate
    仅在创建整个应用程序时才被调用,因此活动在方向或键盘可见性更改时重新启动不会触发它

    将这个类的实例作为一个单例公开,并使用getter和setter公开正在初始化的应用程序变量,这是一个很好的实践

    注意:您需要在清单中指定要注册和使用的新应用程序类的名称:

    或:


    即使更改android的
    方向
    ,仍然会调用
    onCreate
    方法。因此,将所有繁重的功能移到这种方法上并不会对您有所帮助

    我刚刚发现了以下知识:

    通过方向更改使活动保持活动状态,并通过
    onConfigurationChanged
    处理活动,并在清单文件中建议:

    <activity android:name=".MyActivity"
          android:configChanges="orientation|keyboardHidden"
          android:label="@string/app_name">
    
            android:screenOrientation="portrait"
    
    
    
    它还有一个额外的好处,就是它总是有效的

    另外,省略
    键盘隐藏
    似乎合乎逻辑,但它会导致仿真器出现故障(至少对于Android 2.1而言):仅指定
    方向
    将使仿真器调用
    OnCreate
    onConfiguration有时会更改
    ,有时只调用
    OnCreate

    我没有在设备上看到失败,但我听说其他设备的仿真器失败了。所以值得记录。

    我所做的

    在清单的“活动”部分中,添加了:

    android:configChanges="keyboardHidden|orientation"
    
    在活动的代码中,实现了:

    //used in onCreate() and onConfigurationChanged() to set up the UI elements
    public void InitializeUI()
    {
        //get views from ID's
        this.textViewHeaderMainMessage = (TextView) this.findViewById(R.id.TextViewHeaderMainMessage);
    
        //etc... hook up click listeners, whatever you need from the Views
    }
    
    //Called when the activity is first created.
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    
        InitializeUI();
    }
    
    //this is called when the screen rotates.
    // (onCreate is no longer called when screen rotates due to manifest, see: android:configChanges)
    @Override
    public void onConfigurationChanged(Configuration newConfig)
    {
        super.onConfigurationChanged(newConfig);
        setContentView(R.layout.main);
    
        InitializeUI();
    }
    

    您还可以考虑使用Android平台的跨方向性数据持久化的方式:<代码> OnReNeNealDebug()/<代码>和<代码> GETLASTNONFUTCONTION STANSACTIONS()/<代码> 这允许您跨配置更改保存数据,例如您可能从服务器获取的信息或在

    onCreate
    中或之后计算的其他信息,同时还允许Android使用xml文件重新布局您的
    活动

    看到或看到


    应该注意的是,这些方法现在已被弃用(尽管仍然比上述大多数解决方案所建议的自己处理方向更改更灵活),建议每个人都切换到
    Fragments
    ,而改用
    setRetainInstance(true)
    在您要保留的每个
    片段上。

    要在Android清单中进行的更改包括:

    android:configChanges="keyboardHidden|orientation" 
    
    活动中要添加的内容包括:

    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    
        // Checks the orientation of the screen
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
        }
    }
    
    清单的哪个部分告诉它“不要调用
    onCreate()

    而且, 谷歌的文档说要避免使用android:configChanges
    (除非作为最后手段)。。。。但是他们建议的替代方法都使用了
    android:configChanges

    根据我的经验,模拟器在旋转时总是调用
    onCreate()

    但是我运行相同代码的1-2台设备。。。不要。
    (不确定为什么会有任何不同。)

    Android 3.2及更高版本的更新:

    注意:从Android 3.2(API级别13)开始,当设备在纵向和横向之间切换时,“屏幕大小”也会改变。因此,如果要防止在为API级别13或更高版本开发时由于方向更改而重新启动运行时(如minSdkVersion和targetSdkVersion属性所声明的),则必须在
    的“方向”
    值之外添加
    的“屏幕大小”
    值。也就是说,您必须声明
    android:configChanges=“orientation | screenSize”
    。但是,如果您的应用程序的目标API级别为12或更低,则您的活动始终会自行处理此配置更改(此配置更改不会重新启动您的活动,即使在Android 3.2或更高版本的设备上运行时也是如此)

    尽管这不是“Android方式”,但我自己处理方向的变化,并简单地在视图中重新定位小部件,以将改变的方向考虑在内,从而获得了非常好的结果。这比任何其他方法都要快,因为不必保存和恢复视图。它还为用户提供了更无缝的体验,因为重新定位的小部件是完全相同的小部件,只是移动和/或调整了大小。这样不仅可以保存模型状态,还可以保存视图状态

    RelativeLayout
    有时是一个很好的选择
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    
        // Checks the orientation of the screen
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
        }
    }
    
     onConfigurationChanged is called when the screen rotates. 
     (onCreate is no longer called when screen rotates due to manifest, see:  
     android:configChanges)
    
    public void onCreate(Bundle savedInstanceState) {
    
            super.onCreate(savedInstanceState);
    
            setContentView(R.layout.activity_game_list);
    
            if(savedInstanceState == null){
                setupCloudMessaging();
            }
    }
    
         android:configChanges="keyboard|keyboardHidden|orientation"
    
    android:configChanges="orientation"
    
    android:configChanges="orientation"
    
    android:configChanges="keyboardHidden|orientation|screenSize"
    
    android:configChanges="orientation|keyboard|keyboardHidden|screenSize|screenLayout|uiMode"
    
    @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                    WindowManager.LayoutParams.FLAG_FULLSCREEN);
        }
    
    android:configChanges="screenLayout|screenSize|orientation"
    
    @Override
    public void onConfigurationChanged(Configuration myConfig) 
    {
        super.onConfigurationChanged(myConfig);
        int orient = getResources().getConfiguration().orientation; 
        switch(orient) 
        {
           case Configuration.ORIENTATION_LANDSCAPE:
              setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                        break;
           case Configuration.ORIENTATION_PORTRAIT:
              setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                        break;
           default:
              setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        }
    }
    
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
              package="com.pepperonas.myapplication">
    
        <application
            android:name=".App"
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity
                android:name=".MainActivity"
                android:configChanges="orientation|keyboardHidden|screenSize">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
    
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    
    import android.content.res.Configuration;
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentManager;
    import android.support.v4.app.FragmentTransaction;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    
        private static final String TAG = "MainActivity";
    
        private Fragment mFragment;
    
        private int mSelected = -1;
    
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.d(TAG, "onCreate  " + "");
    
            // null check not realy needed - but just in case...
            if (savedInstanceState == null) {
    
                initUi();
    
                // get an instance of FragmentTransaction from your Activity
                FragmentManager fragmentManager = getSupportFragmentManager();
                FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    
                /*IMPORTANT: Do the INITIAL(!) transaction only once!
                * If we call this everytime the layout changes orientation,
                * we will end with a messy, half-working UI.
                * */
                mFragment = FragmentOne.newInstance(mSelected = 0);
                fragmentTransaction.add(R.id.frame, mFragment);
                fragmentTransaction.commit();
            }
        }
    
    
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
            Log.d(TAG, "onConfigurationChanged  " +
                       (newConfig.orientation
                        == Configuration.ORIENTATION_LANDSCAPE
                        ? "landscape" : "portrait"));
    
            initUi();
    
            Log.i(TAG, "onConfigurationChanged - last selected: " + mSelected);
            makeFragmentTransaction(mSelected);
        }
    
    
        /**
         * Called from {@link #onCreate} and {@link #onConfigurationChanged}
         */
        private void initUi() {
            setContentView(R.layout.activity_main);
            Log.d(TAG, "onCreate  instanceState == null / reinitializing..." + "");
            Button btnFragmentOne = (Button) findViewById(R.id.btn_fragment_one);
            Button btnFragmentTwo = (Button) findViewById(R.id.btn_fragment_two);
            btnFragmentOne.setOnClickListener(this);
            btnFragmentTwo.setOnClickListener(this);
        }
    
    
        /**
         * Not invoked (just for testing)...
         */
        @Override
        protected void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            Log.d(TAG, "onSaveInstanceState  " + "YOU WON'T SEE ME!!!");
        }
    
    
        /**
         * Not invoked (just for testing)...
         */
        @Override
        protected void onRestoreInstanceState(Bundle savedInstanceState) {
            super.onRestoreInstanceState(savedInstanceState);
            Log.d(TAG, "onSaveInstanceState  " + "YOU WON'T SEE ME, AS WELL!!!");
        }
    
    
        @Override
        protected void onResume() {
            super.onResume();
            Log.d(TAG, "onResume  " + "");
        }
    
    
        @Override
        protected void onPause() {
            super.onPause();
            Log.d(TAG, "onPause  " + "");
        }
    
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            Log.d(TAG, "onDestroy  " + "");
        }
    
    
        @Override
        public void onClick(View v) {
    
            switch (v.getId()) {
                case R.id.btn_fragment_one:
                    Log.d(TAG, "onClick btn_fragment_one " + "");
                    makeFragmentTransaction(0);
                    break;
    
                case R.id.btn_fragment_two:
                    Log.d(TAG, "onClick btn_fragment_two " + "");
                    makeFragmentTransaction(1);
                    break;
    
                default:
                    Log.d(TAG, "onClick  null - wtf?!" + "");
            }
        }
    
    
        /**
         * We replace the current Fragment with the selected one.
         * Note: It's called from {@link #onConfigurationChanged} as well.
         */
        private void makeFragmentTransaction(int selection) {
    
            switch (selection) {
                case 0:
                    mFragment = FragmentOne.newInstance(mSelected = 0);
                    break;
                case 1:
                    mFragment = FragmentTwo.newInstance(mSelected = 1);
                    break;
            }
    
            // Create new transaction
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    
            // Replace whatever is in the fragment_container view with this fragment,
            // and add the transaction to the back stack
            transaction.replace(R.id.frame, mFragment);
    
            /*This would add the Fragment to the backstack...
            * But right now we comment it out.*/
            //        transaction.addToBackStack(null);
    
            // Commit the transaction
            transaction.commit();
        }
    
    }
    
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    
    /**
     * @author Martin Pfeffer (pepperonas)
     */
    public class FragmentOne extends Fragment {
    
        private static final String TAG = "FragmentOne";
    
    
        public static Fragment newInstance(int i) {
            Fragment fragment = new FragmentOne();
            Bundle args = new Bundle();
            args.putInt("the_id", i);
            fragment.setArguments(args);
            return fragment;
        }
    
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            Log.d(TAG, "onCreateView  " + "");
            return inflater.inflate(R.layout.fragment_one, container, false);
        }
    
    }
    
    <activity
        android:name=".Test"
        android:configChanges="orientation|screenSize"
        android:screenOrientation="landscape" >
    </activity>
    
    @Override
    public void onSaveInstanceState(Bundle outState) {
        /*Save your data to be restored here
        Example : outState.putLong("time_state", time); , time is a long variable*/
        super.onSaveInstanceState(outState);
    }
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        if(savedInstanceState!= null){
           /*When rotation occurs
            Example : time = savedInstanceState.getLong("time_state", 0); */
        } else {
          //When onCreate is called for the first time
        }
    }
    
    android:configChanges="keyboardHidden|orientation"
    
    android:configChanges="keyboardHidden|orientation|screenSize"
    
    @Override
    public void onConfigurationChanged(Configuration config) {
        super.onConfigurationChanged(config);
    
    if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            //Handle rotation from landscape to portarit mode here
        } else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
            //Handle rotation from portrait to landscape mode here
        }
    }
    
            android:screenOrientation="portrait"
    
    @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }
    
    @Override
        public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
            super.onSaveInstanceState(outState, outPersistentState);
            outPersistentState.putBoolean("key",value);
        }
    
    @Override
        protected void onRestoreInstanceState(Bundle savedInstanceState) {
            super.onRestoreInstanceState(savedInstanceState);
            savedInstanceState.getBoolean("key");
        } 
    
      <activity android:name=".Youractivity"
      android:configChanges="orientation|screenSize"/>
    
    android:configChanges="keyboardHidden|orientation"
    
    android:configChanges="keyboardHidden|orientation"
    
    class MyViewModel : ViewModel() {