我有一个不会在方向更改后重新创建的活动.我在清单中的活动声明中添加了以下内容:
android:configChanges="orientation"
Run Code Online (Sandbox Code Playgroud)
在Android 2.3上,这非常有效.在更改方向时,无论如何都会调用HONEYCOMB_MR2 onCreate.
是否还需要在HONEYCOMB_MR2上执行其他操作以防止在方向更改后重新创建活动?
android screen-orientation android-configchanges android-3.0-honeycomb
我有一个非常奇怪的问题.我有一个常见的片段,几乎在我的应用程序的每个活动中都添加了.此片段显示了一个小版本的播放器栏.所以它会收听一些广播以更新当前音乐的名称,并有一些控制,如播放/暂停.
就像我说的,我几乎在我的应用程序的每个活动中都添加了这个片段,我从来没有遇到任何问题.但现在,我需要创建一个没有UI且保留的新片段(setRetainInstance(true)).添加这个新片段后,一切似乎都没问题.直到我旋转设备并且活动崩溃.
所以,查看日志,我看到以下异常:
07-05 14:10:23.818: ERROR/AndroidRuntime(25922): FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.soongz/com.soongz.ui.PlaylistActivity}: android.view.InflateException: Binary XML file line #13: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2110)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2135)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3576)
at android.app.ActivityThread.access$800(ActivityThread.java:140)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1243)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4921)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.view.InflateException: Binary XML file line #13: Error inflating class fragment
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:313)
at com.actionbarsherlock.internal.ActionBarSherlockNative.setContentView(ActionBarSherlockNative.java:119)
at …Run Code Online (Sandbox Code Playgroud) 有什么意义:
super.onCreate(null);
Run Code Online (Sandbox Code Playgroud)
代替
super.onCreate(savedInstanceState);
Run Code Online (Sandbox Code Playgroud)
通过这种改变,我能够避免许多问题,否则Activity每次发生配置更改时都会困扰我(旋转,区域设置转换,权限切换).似乎通过此更改,Activity只要配置更改触发重新启动,就会重新启动.而且我似乎没有丢失任何数据或进程状态:我Activity的所有s都完全恢复到以前的状态.
我的问题是,我今后可以逍遥法外,或者在讨价还价中丢失一些东西吗?我真的不明白为什么这样做,无论是否安全,以及它对我的应用程序可能产生的意外影响.
我偶然发现这一招在这里.
相关问题:
android android-lifecycle android-configchanges android-activity android-savedstate
我注意到,当从一个Activity处理配置更改时,onLayout和onSizeChanged会在方向更改后立即连续调用两次,无论是从landscape-> portrait还是从portrait-> landscape.此外,第一个onLayout/onSizeChanged包含旧维度(在旋转之前),而第二个onLayout/onSizeChanged包含新(正确)维度.
有谁知道为什么,和/或如何解决这个问题?似乎在配置更改后很长一段时间内屏幕尺寸发生了变化 - 也就是说,在onConfigurationChanged调用配置更改后立即尺寸不正确?
这是下面代码的调试输出,显示从Portrait到Landscape旋转后的onLayout/onSizeChanged调用(请注意,设备为540x960,因此横向宽度应为960,纵向宽度为540):
03-13 17:36:21.140: DEBUG/RotateTest(27765): onConfigurationChanged: LANDSCAPE
03-13 17:36:21.169: DEBUG/RotateTest(27765): onSizeChanged:540,884,0,0
03-13 17:36:21.189: DEBUG/RotateTest(27765): onLayout:true-0,0,540,884
03-13 17:36:21.239: DEBUG/RotateTest(27765): onSizeChanged:960,464,540,884
03-13 17:36:21.259: DEBUG/RotateTest(27765): onLayout:true-0,0,960,464
Run Code Online (Sandbox Code Playgroud)
另请注意,第一个onSizeChanged oldwidth和oldheight为0,表示我们刚刚添加到视图层次结构中 - 但是景观的尺寸错误!
以下是说明此行为的代码:
package com.example;
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.widget.FrameLayout;
public class MyActivity extends Activity
{
private static String TAG = "RotateTest";
@Override
public void onConfigurationChanged(Configuration newConfig) {
Log.d(TAG, "onConfigurationChanged: " + (newConfig.orientation == …Run Code Online (Sandbox Code Playgroud) android android-layout android-configchanges android-orientation
我一直在查看stackoverflow中的问题,我已经尝试了所有我见过但布局 - 土地不起作用.在我的代码中,我有和方法onConfigurationChanged
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
Run Code Online (Sandbox Code Playgroud)
和清单文件:
<activity
android:name="com.sde.PlayerTrack"
android:theme="@style/AppTheme"
android:configChanges="orientation|keyboardHidden|screenSize"
>
</activity>
Run Code Online (Sandbox Code Playgroud)
我也尝试删除android清单条目:configChanges然后布局陆载,但我有的组件(TextView,滚动条...)不能正常工作.
你能帮我吗?
对不起我的英语不好
我应该通过\来保存和恢复配置更改getArguments()期间的参数(返回)吗?outStatesavedInstanceState
或者getArguments()总是在配置更改后返回传递的参数?
我想非UI片段的主要目的是通过配置更改保留数据的存储,对吧?因此,从这个存储专用于拥有此片段的Activity,这是它在整个应用程序中使用Singleton模式的好处(这是我迄今为止所做的解决方案)?
我正在尝试实现一种布局,当设备显示在纵向上时显示视图寻呼机,并在设备处于横向时显示两个窗格.
所以我制作了两个不同的布局文件,一个只有一个ViewPager,另一个有一个LinearLayout,另一个有两个FrameLayout,我不认为有必要在这里显示它们.hasTwoPanes两种配置也有一个布尔值.
@Inject FragmentOne fragmentOne;
@Inject FragmentTwo fragmentTwo;
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.activity_main);
FragmentManager fm = getSupportFragmentManager();
boolean hasTwoPanes = getResources().getBoolean(R.bool.hasTwoPanes);
TabLayout tabLayout = findViewById(R.id.tab_layout);
ViewPager viewPager = findViewById(R.id.view_pager);
if (hasTwoPanes) {
tabLayout.setVisibility(View.GONE);
} else {
tabLayout.setVisibility(View.VISIBLE);
tabLayout.setupWithViewPager(viewPager);
viewPager.setAdapter(new MyPagerAdapter(fm));
}
FragmentOne frag1 = (FragmentOne) fm.findFragmentByTag(getFragmentName(0));
if (frag1 != null) fragmentOne = frag1;
FragmentTwo frag2 = (FragmentTwo) fm.findFragmentByTag(getFragmentName(1));
if (frag2 != null) fragmentTwo = frag2;
if (hasTwoPanes) {
if (frag1 != null) {
fm.beginTransaction().remove(fragmentOne).commit();
fm.beginTransaction().remove(fragmentTwo).commit(); …Run Code Online (Sandbox Code Playgroud) android android-configchanges android-fragments android-viewpager
更新:事实证明问题来自其他地方.感谢@Luksprog指出我忽略了什么.
NavigationDrawerFragment课堂上实施.onCreate()方法NavigationDrawerFragment,保留最后选择的项目.NavigationDrawerFragment会再次调用selectItem(),这会触发我的菜单项选择处理程序.这会导致Android恢复ListFragment.通过检查菜单选择处理程序代码中的活动菜单项可以防止这种情况.
我想保留最后一个查看页面索引,该索引ViewPager是由任何原因重新创建活动的时间,例如方向更改.
的ViewPager是在Fragment(命名ListFragment),其被附接到的活性.我正在使用compat库,因此片段是它的子类android.support.v4.app.Fragment.
我认为可以通过覆盖onSaveInstanceState()方法并添加适当的逻辑来完成onCreate(),如文档中所述:
要正确处理重新启动,您的活动必须通过正常的Activity生命周期恢复其先前的状态,在此生命周期中Android会在销毁活动之前调用onSaveInstanceState(),以便您可以保存有关应用程序状态的数据.然后,您可以在onCreate()或onRestoreInstanceState()期间恢复状态.
但是片段的情况似乎不同.当我从此导航ListFragment到另一个活动并按下"返回" 时,可以正确恢复页面索引.但是,当我旋转设备时,页面索引会丢失.
我添加了一些日志记录,看看有什么问题.从日志中我发现,虽然onSaveInstanceState() 的ListFragment(我称之为ListFragment A)正确调用,这个特殊的片段类不再在活动中.当方向改变并重新创建活动时,Android调用onSaveInstanceState()后跟onDetach()分离此片段.然后,Android会创建一个新实例ListFragment(我将其命名为ListFragment B)并将其附加到新的旋转活动中.此ListFragment B将空savedInstanceState传递给构造函数,因此最后一页索引(以及片段A的savedInstanceState中的任何配置)都将丢失.
实际上,ListFragment每次屏幕旋转时都会创建一个新实例,但似乎旧的实例不会被销毁.我在旋转设备时会看到如下所示的日志:
D/ListFragment? [1110257048] onSaveInstanceState() called, storing last page index 3
D/ListFragment? [1109835992] onSaveInstanceState() called, storing last page index 0
D/ListFragment? …Run Code Online (Sandbox Code Playgroud) 我的网络应用程序在Chrome中运行良好,可以很好地处理配置更改(例如屏幕旋转).一切都完好无损.
将我的网络应用加载到WebView我的Android应用中时,网络应用会在屏幕方向更改时失去状态.它确实部分保留了状态,即它保留了<input>表单元素的数据,但是所有的JavaScript变量和DOM操作都会丢失.
我希望我的WebView能够像Chrome一样运行,即完全保留状态,包括任何JavaScript变量.需要注意的是,虽然Chrome和WebView源自相同的代码库,但Chrome内部不使用WebView.
屏幕方向更改发生的情况是Activity(以及任何最终的片段)被销毁然后随后重新创建.WebView继承View和覆盖方法onSaveInstanceState以及 onRestoreInstanceState处理配置更改因此它会自动保存和恢复任何HTML表单元素的内容以及后退/前进导航历史状态.但是,不保存和恢复JavaScript变量和DOM的状态.
已经提出了一些解决方案.所有这些都是非工作的,只保留部分状态或其他方式不理想.
WebView继承了View具有方法的方法setId,该方法也可以使用元素android:id声明中的属性在布局XML文件中声明<WebView>.这是保存和恢复状态所必需的,但状态仅部分恢复.这将恢复表单输入元素,但不恢复JavaScript变量和DOM的状态.
并且自API级别13以来onRetainNonConfigurationInstance已弃用.getLastNonConfigurationInstance
通过在文件中或通过方法设置元素的screenOrientation属性,可以强制活动屏幕方向.这是不希望的,因为它打破了屏幕旋转的期望.这也只涉及屏幕方向的变化而不是其他配置变化.<Activity>AndroidManifest.xmlsetRequestedOrientation
不行.setRetainInstance在片段上调用方法确实会保留片段(它不会被破坏),因此片段的所有实例变量都会被保留,但是它会破坏片段的视图,因此WebView它会被破坏.
该configChanges属性可以被声明为Activity中AndroidManifest.xml文件android:configChanges="orientation|screenSize"处理配置更改,防止它们.这有效,它可以防止活动被破坏,因此WebView它的内容被完全保留.然而,这是不鼓励的,并且据说仅作为最后的解决方案使用,因为它可能导致应用程序以微妙的方式打破并且变得越来越多.设置属性onConfigurationChanged时会调用该方法configChanges.
我听说MutableContextWrapper可以使用,但我没有评估这种方法.
WebView有方法saveState和 …
android webview android-webview android-configchanges android-view