在我的Android应用程序中,当我旋转设备(滑出键盘)时,“活动”将重新启动(调用onCreate)。现在,这可能是应该的,但我在onCreate方法中做了很多初始设置,所以我需要:
将所有初始设置放在另一个功能中,这样不会在设备旋转或使其不再调用Create,布局仅调整或将应用程序限制为仅肖像,以便不调用onCreate。
在我的Android应用程序中,当我旋转设备(滑出键盘)时,“活动”将重新启动(调用onCreate)。现在,这可能是应该的,但我在onCreate方法中做了很多初始设置,所以我需要:
将所有初始设置放在另一个功能中,这样不会在设备旋转或使其不再调用Create,布局仅调整或将应用程序限制为仅肖像,以便不调用onCreate。
当前回答
谷歌推出的android架构中最好的组件之一将满足ViewModel的所有要求。
它旨在以生命周期的方式存储和管理与UI相关的数据,并允许数据在屏幕旋转时继续存在
class MyViewModel : ViewModel() {
请参阅:https://developer.android.com/topic/libraries/architecture/viewmodel
其他回答
很简单,只需执行以下步骤:
<activity
android:name=".Test"
android:configChanges="orientation|screenSize"
android:screenOrientation="landscape" >
</activity>
这对我有用:
注意:方向取决于你的要求
注意:如果将来有人和我面临同样的问题,我会发布这个答案。对我来说,下面这行是不够的:
android:configChanges="orientation"
当我旋转屏幕时,没有调用方法`onConfigurationChanged(配置新配置)。
解决方案:即使问题与方向有关,我也必须添加“screenSize”。因此,在AndroidManifest.xml文件中,添加以下内容:
android:configChanges="keyboardHidden|orientation|screenSize"
然后实现方法onConfigurationChanged(Configuration newConfig)
经过一段时间的反复尝试,我找到了一个在大多数情况下都能满足我需求的解决方案。以下是代码:
清单配置:
<?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);
}
}
可以在github上找到。
Android 3.2及更高版本更新:
警告:从Android 3.2(API级别13)开始,当设备在纵向和横向方向之间切换时,“屏幕大小”也会发生变化。因此,如果在为API级别13或更高级别开发时(如minSdkVersion和targetSdkVersion属性所声明的),想要防止因方向改变而导致运行时重新启动,则除了“方向”值之外,还必须包含“screenSize”值。也就是说,您必须声明android:configChanges=“orientation|screenSize”。但是,如果您的应用程序以API级别12或更低为目标,则您的活动始终自行处理此配置更改(即使在Android 3.2或更高版本的设备上运行时,此配置更改也不会重新启动您的活动)。
从…起http://web.archive.org/web/20120805085007/http://developer.android.com/guide/topics/resources/runtime-更改.html
您可以在活动中使用ViewModel对象。
ViewModel对象在配置更改期间自动保留,以便它们所保存的数据可立即用于下一个活动或片段实例。阅读更多信息:https://developer.android.com/topic/libraries/architecture/viewmodel