片段和 onConfigurationChanged
Posted
技术标签:
【中文标题】片段和 onConfigurationChanged【英文标题】:fragments and onConfigurationChanged 【发布时间】:2013-04-23 08:39:37 【问题描述】:我正在尝试用活动做一些事情,但在一个片段内。 我所做的是使用活动:
旋转设备时首先停止活动重新启动
android:configChanges="keyboardHidden|orientation|screenSize"
在我的活动中添加:
@Override
public void onConfigurationChanged(Configuration newConfig)
super.onConfigurationChanged(newConfig);
setContentView(R.layout.main);
所以拿到activity并没有重启,而是重新加载main.xml,来使用layout-land
现在我有一个显示 viewpager 的活动,其中包含三个片段。 一切正常。旋转检测是在片段中
public class FRG_map_web extends Fragment
@Override
public void onConfigurationChanged(Configuration newConfig)
super.onConfigurationChanged(newConfig);
Log.i("myLogs", "Rotation");
问题是片段没有使用 setContentView(R.layout.main);这是代码:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
view = inflater.inflate(R.layout.frg.myFragment, null);
我尝试使用:
LayoutInflater inflater = inflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.frg.myFragment, null);
...
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.frg.myFragment, null);
...
LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
view = inflater.inflate(R.layout.frg.myFragment, null);
...
LayoutInflater li = LayoutInflater.from(context);
和不同的方式,但总是没有成功 我无法正常充气。
谁能告诉我该怎么做?
在此先感谢,感谢您的帮助
问候
【问题讨论】:
你的问题一点都不清楚。您是否尝试在旋转后重新创建片段? 我的意图是旋转设备后不重启activity,而是fragment的onConfigurationChanged,重新加载布局xml 你会遇到android:configChanges
的问题,因为在大多数情况下,你不应该使用它。您没有考虑到许多类型的配置更改。 onSavedInstanceState
是你的朋友。
我在片段中使用位图,如果每次旋转设备时片段都会重新加载,我会遇到“内存不足”的问题。第一次加载是受控的,而不是其余的(如何旋转),所以我只需要加载一次
因为位图而覆盖 android:configChanges
是一个糟糕的借口。您必须通过onSavedInstanceState
在配置更改之间保留位图。
【参考方案1】:
如果我理解正确,您不希望片段在每次旋转时重新加载。相反,您希望重新布局视图并使用您已有的信息更新它们。
public void onConfigurationChanged(Configuration newConfig)
super.onConfigurationChanged(newConfig);
// Get a layout inflater (inflater from getActivity() or getSupportActivity() works as well)
LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View newView = inflater.inflate(R.layout.frg.myFragment, null);
// This just inflates the view but doesn't add it to any thing.
// You need to add it to the root view of the fragment
ViewGroup rootView = (ViewGroup) getView();
// Remove all the existing views from the root view.
// This is also a good place to recycle any resources you won't need anymore
rootView.removeAllViews();
rootView.addView(newView);
// Viola, you have the new view setup
根据文档 (getView()),getView() 返回的视图与您从 onCreateView() 返回的视图相同,但事实并非如此。它实际上返回您在 onCreateView() 中返回的视图的父级,这正是您所需要的。 getView() 将返回一个 NoSaveStateFrameLayout 的实例,该实例专门用于 Fragments 作为其根视图。
希望这会有所帮助。
【讨论】:
我认为这是一个很好的解决方案,但我得到一个力关闭,不知道为什么。我放了一个关于日志的日志 ul.to/arq9y8gj 的链接,我也尝试过不使用 actionbarsherlock,错误仍然存在 从错误日志中检查,您似乎遇到了重复片段的错误。检查此解决方案***.com/questions/14083950/… 感谢 lika a Charm 工作 如果您的视图有任何其他布局而不是左上角,您需要在新视图上再次设置布局参数。不过,您可以从上一个得到这个:ViewGroup.LayoutParams lp = rootView.getChildAt(0).getLayoutParams(); newView.setLayoutParams(lp);
我试过了:查看 newView = inflater.inflate(R.layout.frg.myFragment, null);但收到警告,所以我稍微修改了代码:(1)我先声明 rootView(2)改为调用它“View newView = inflater.inflate(R.layout.my frag, rootView, false);”最终结果相同,但没有警告。 :)【参考方案2】:
您是否考虑过保留您的片段实例?见Fragment#setRetainInstance。
允许重新创建您的 Activity(不要指定 android:configChanges),但在方向更改时保留您的片段实例。如果所有繁重的工作都发生在 Fragment#onCreate 这应该可以正常工作。 onCreate() 不会被再次调用,因为片段没有被重新创建。
【讨论】:
onCreateView() 被再次调用以创建新的视图层次结构。应该可以保留位图并在新创建的视图中重用它们。【参考方案3】:我可以通过在 onConfigurationChanged 中重新附加片段来做到这一点:
@Override
public void onConfigurationChanged(Configuration newConfig)
getActivity().detachFragment(this);
super.onConfigurationChanged(newConfig);
....
getActivity().attachFragment(this);
请记住,通过分离和附加您的片段,您将只使用它的视图。但是片段状态在片段管理器中被“保存”了。
【讨论】:
Activity.[detach|attach]Fragment() 方法不存在,必须使用 FragmentManager.beginTransaction().[detach|attach]()。【参考方案4】:您可以尝试分离和附加片段:
@Override
public void onConfigurationChanged(Configuration newConfig)
FragmentManager fragmentManager = getFragmentManager();
if (fragmentManager != null)
fragmentManager.beginTransaction().detach(this).commitAllowingStateLoss();
super.onConfigurationChanged(newConfig);
if (fragmentManager != null)
fragmentManager.beginTransaction().attach(this).commitAllowingStateLoss();
【讨论】:
【参考方案5】:也许你可以尝试使用
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
view = inflater.inflate(R.layout.frg.myFragment, container, false);
。无论如何,fragment 还是要被销毁和重新创建的,为什么不让 Android 通过重启 Activity 来自动处理呢?如果有需要保留的数据,可以保存在onSavedInstanceState()
。不建议在 Android 中设置android:configChanges="keyboardHidden|orientation|screenSize"
。
【讨论】:
以上是关于片段和 onConfigurationChanged的主要内容,如果未能解决你的问题,请参考以下文章
移动到 1/3 屏幕宽度时未调用 onConfigurationChanged
内存泄漏通过onConfigurationChanged()
onConfigurationChanged 屏幕停止在设备上旋转。在模拟器上工作
Android开发,重写了onConfigurationChanged方法。横屏切换竖屛不会重建,而竖屛切换横屏却仍会重建活动