片段,地图应用程序崩溃时,后退按钮是pressed或者方向变化 [英] Fragment with Map crashes app when back button is pressed or when orientation changes
问题描述
我有一个活动
,加载2个选项卡中的动作条
。标签1会装载片段
将将抬高一个的WebView
,而标签2加载一个片段
的地图。起初,我有改变的选项卡,导致应用程序崩溃的问题。我也跟着指示<一href="http://stackoverflow.com/questions/14074625/mapfragment-in-action-bar-tabs/14466954#14466954">here实施 onDestroyView()
。
现在的问题是,如果我preSS后退按钮由表1(的WebView
),它退出活动
正常。但是,如果我这样做的选项卡2(图),该应用程序崩溃。确切相同的情况时,我改变方向。我相信,它有事可做与 onDestroyView()
,但我不知道它是什么。
我甚至尝试覆盖
返回按钮,但没有任何工程。
下面是我的code提供一些背景:
Activity类:
公共类MyActivity延伸活动{
@覆盖
保护无效的onCreate(包savedInstanceState){
super.onCreate(savedInstanceState);
的setContentView(R.layout.activity_main);
//调用动作条显示卡
动作条动作条= getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
//详细信息选项卡
。字符串卷标1 = getResources()的getString(R.string.details);
TAB键= actionBar.newTab();
tab.setText(LABEL1);
TabListener&LT; DetailsFragment&GT; T1 =新TabListener&LT; DetailsFragment&GT;(这一点,LABEL1,DetailsFragment.class);
tab.setTabListener(T1);
actionBar.addTab(标签);
//地图标签
。字符串标签2 = getResources()的getString(R.string.map);
标签= actionBar.newTab();
tab.setText(LABEL2);
TabListener&LT; MapFragment&GT; T2 =新TabListener&LT; MapFragment&GT;(这一点,LABEL2,MapFragment.class);
tab.setTabListener(T2);
actionBar.addTab(标签);
}
私有类TabListener&LT;吨延伸片断&gt;实现ActionBar.TabListener {
私人片段mFragment;
私人最终活动mActivity;
私人最终字符串MTAG;
私人最终类别&LT; T&GT; mClass;
/ **
*构造函数用于创建一个新的标签,每次。
*
* @参数活动
*主机活动,用实例片段
* @参数标签
*标识符标记的片段
* @参数CLZ
*片段的类,用于实例片段
* /
公共TabListener(活动活动,字符串变量,类&LT; T&GT; CLZ){
mActivity =活动;
MTAG =标签;
mClass = CLZ;
}
公共无效onTabSelected(TAB键,FragmentTransaction英尺){
//检查片段已初始化
如果(mFragment == NULL){
//如果没有,实例化并把它添加到活动
mFragment = Fragment.instantiate(mActivity,mClass.getName());
ft.add(android.R.id.content,mFragment,MTAG);
} 其他 {
//如果它存在,只需将它为了显示它
ft.attach(mFragment);
}
}
公共无效onTabUnselected(TAB键,FragmentTransaction英尺){
如果(mFragment!= NULL){
//分离的片段,因为另一个被连接
ft.detach(mFragment);
}
}
公共无效onTabReselected(TAB键,FragmentTransaction英尺){
//用户选择已经选择的选项卡。通常什么也不做。
}
}
@覆盖
公共布尔onCreateOptionsMenu(功能菜单){
//充气菜单;这增加了项目操作栏,如果它是present。
。getMenuInflater()膨胀(R.menu.main,菜单);
返回true;
}}
DetailsFragment:
公共类DetailsFragment扩展片段{
@覆盖
公共查看onCreateView(LayoutInflater充气,容器的ViewGroup,捆绑savedInstanceState){
视图V = inflater.inflate(R.layout.morning,集装箱,假);
的WebView的WebView =(web视图)v.findViewById(R.id.details);
webview.loadUrl(文件:///android_asset/pools/details.html);
返回伏;
}}
MapFragment:
公共类MapFragment扩展片段{
static final的经纬度mapLatLng =新的经纬度(一些数字,有些数字);
私人GoogleMap的地图;
@覆盖
公共查看onCreateView(LayoutInflater充气,容器的ViewGroup,捆绑savedInstanceState){
视图V = inflater.inflate(R.layout.map,集装箱,假);
地图=((MapFragment)getFragmentManager()findFragmentById(R.id.map)。)的GetMap()。
标记amksc = map.addMarker(新MarkerOptions()位置(mapLatLng).title伪(地图));
map.moveCamera(CameraUpdateFactory.newLatLngZoom(mapLatLng,18));
返回伏;
}
@覆盖
公共无效onDestroyView(){
super.onDestroyView();
MapFragment destroyMe =(MapFragment)getFragmentManager()findFragmentById(R.id.map)。
如果(destroyMe!= NULL){
。getFragmentManager()的BeginTransaction()删除(destroyMe).commit()。
}
}}
感谢您阅读这么长的帖子。任何帮助是极大的AP preciated。我要离开一段时间没有我的笔记本电脑(15天是精确的),所以我可能无法作出反应,并测试出你的答案,但请放心,我会=)
在此先感谢!
编辑,包括错误日志(不知道如何格式化)
11月四号至25日:27:54.333:E / AndroidRuntime(21779):致命异常:主要
11月4号至25日:27:54.333:E / AndroidRuntime(21779):显示java.lang.NullPointerException
11月4号至25日:27:54.333:E / AndroidRuntime(21779):在android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1380)
11月4号至25日:27:54.333:E / AndroidRuntime(21779):在android.app.FragmentManagerImpl $ 1.运行(FragmentManager.java:430)
11月4号至25日:27:54.333:E / AndroidRuntime(21779):在android.os.Handler.handleCallback(Handler.java:615)
11月4号至25日:27:54.333:E / AndroidRuntime(21779):在android.os.Handler.dispatchMessage(Handler.java:92)
11月4号至25日:27:54.333:E / AndroidRuntime(21779):在android.os.Looper.loop(Looper.java:213)
11月4号至25日:27:54.333:E / AndroidRuntime(21779):在android.app.ActivityThread.main(ActivityThread.java:4786)
11月4号至25日:27:54.333:E / AndroidRuntime(21779):在java.lang.reflect.Method.invokeNative(本机方法)
11月4号至25日:27:54.333:E / AndroidRuntime(21779):在java.lang.reflect.Method.invoke(Method.java:511)
11月4号至25日:27:54.333:E / AndroidRuntime(21779):在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:789)
11月4号至25日:27:54.333:E / AndroidRuntime(21779):在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
11月4号至25日:27:54.333:E / AndroidRuntime(21779):在dalvik.system.NativeStart.main(本机方法)
我似乎已经解决了这两个后退按钮和方向变化的问题。
这里的技巧是不使用 onDestroyView()
,而是要改变片段的处理方式。而不是 ft.attach(mFragment)
和 ft.detach(mFragment)
,我改变了他们为 ft.show(mFragment)
和 ft.hide(mFragment)
。
对于方向的改变导致应用程序崩溃,我相信(不纠正我,如果我错了),只要你没有一个替代的景观布局,您可以添加安卓configChanges =方向|屏幕尺寸
的清单这项活动,像这样的:
&LT;活动
机器人:主题=@风格/ AppTheme
机器人:名称=MyFragmentActivity
机器人:标签=@字符串/ fragmentActivity
机器人:configChanges =方向|屏幕尺寸&GT;
&LT; /活性GT;
I have an Activity
that loads 2 tabs in the ActionBar
. Tab 1 loads a Fragment
that will will inflate a WebView
, while Tab 2 loads a Fragment
with a map. Initially, I have the problem of changing tabs that causes the app to crash. I have followed the instructions here and implemented onDestroyView()
.
The problem now is that if I press the back button from Tab 1 (WebView
), it exits the Activity
properly. But if I do it on Tab 2 (map), the app crashes. The exact same scenario applies to when I change the orientation. I am convinced that it has something to do with the onDestroyView()
, but I am not sure what it is.
I have even attempted to Override
the back button, but nothing works.
Here is my code to provide some context:
The Activity Class:
public class MyActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Displaying the tabs by calling ActionBar
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
//Details Tab
String label1 = getResources().getString(R.string.details);
Tab tab = actionBar.newTab();
tab.setText(label1);
TabListener<DetailsFragment> t1 = new TabListener<DetailsFragment>(this, label1, DetailsFragment.class);
tab.setTabListener(t1);
actionBar.addTab(tab);
//Map Tab
String label2 = getResources().getString(R.string.map);
tab = actionBar.newTab();
tab.setText(label2);
TabListener<MapFragment> t2 = new TabListener<MapFragment>(this, label2, MapFragment.class);
tab.setTabListener(t2);
actionBar.addTab(tab);
}
private class TabListener<T extends Fragment> implements ActionBar.TabListener {
private Fragment mFragment;
private final Activity mActivity;
private final String mTag;
private final Class<T> mClass;
/**
* Constructor used each time a new tab is created.
*
* @param activity
* The host Activity, used to instantiate the fragment
* @param tag
* The identifier tag for the fragment
* @param clz
* The fragment's Class, used to instantiate the fragment
*/
public TabListener(Activity activity, String tag, Class<T> clz) {
mActivity = activity;
mTag = tag;
mClass = clz;
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// Check if the fragment is already initialized
if (mFragment == null) {
// If not, instantiate and add it to the activity
mFragment = Fragment.instantiate(mActivity, mClass.getName());
ft.add(android.R.id.content, mFragment, mTag);
} else {
// If it exists, simply attach it in order to show it
ft.attach(mFragment);
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
if (mFragment != null) {
// Detach the fragment, because another one is being attached
ft.detach(mFragment);
}
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// User selected the already selected tab. Usually do nothing.
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
} }
DetailsFragment:
public class DetailsFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.morning, container, false);
WebView webview = (WebView) v.findViewById(R.id.details);
webview.loadUrl("file:///android_asset/pools/details.html");
return v;
} }
MapFragment:
public class MapFragment extends Fragment {
static final LatLng mapLatLng = new LatLng("some numbers", "some numbers");
private GoogleMap map;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.map, container, false);
map = ((MapFragment)getFragmentManager().findFragmentById(R.id.map)).getMap();
Marker amksc = map.addMarker(new MarkerOptions().position(mapLatLng).title("Map"));
map.moveCamera(CameraUpdateFactory.newLatLngZoom(mapLatLng, 18));
return v;
}
@Override
public void onDestroyView() {
super.onDestroyView();
MapFragment destroyMe = (MapFragment)getFragmentManager().findFragmentById(R.id.map);
if (destroyMe != null) {
getFragmentManager().beginTransaction().remove(destroyMe).commit();
}
} }
Thanks for reading such a long post. Any help is greatly appreciated. I will be away for awhile without my laptop (15 days to be exact), so I may not be able to respond and test out your answer, but rest assured that I will =)
Thanks in advance!
EDITED to include Error Log (Not sure how to format it)
04-25 11:27:54.333: E/AndroidRuntime(21779): FATAL EXCEPTION: main
04-25 11:27:54.333: E/AndroidRuntime(21779): java.lang.NullPointerException
04-25 11:27:54.333: E/AndroidRuntime(21779): at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1380)
04-25 11:27:54.333: E/AndroidRuntime(21779): at android.app.FragmentManagerImpl$1.run(FragmentManager.java:430)
04-25 11:27:54.333: E/AndroidRuntime(21779): at android.os.Handler.handleCallback(Handler.java:615)
04-25 11:27:54.333: E/AndroidRuntime(21779): at android.os.Handler.dispatchMessage(Handler.java:92)
04-25 11:27:54.333: E/AndroidRuntime(21779): at android.os.Looper.loop(Looper.java:213)
04-25 11:27:54.333: E/AndroidRuntime(21779): at android.app.ActivityThread.main(ActivityThread.java:4786)
04-25 11:27:54.333: E/AndroidRuntime(21779): at java.lang.reflect.Method.invokeNative(Native Method)
04-25 11:27:54.333: E/AndroidRuntime(21779): at java.lang.reflect.Method.invoke(Method.java:511)
04-25 11:27:54.333: E/AndroidRuntime(21779): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
04-25 11:27:54.333: E/AndroidRuntime(21779): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
04-25 11:27:54.333: E/AndroidRuntime(21779): at dalvik.system.NativeStart.main(Native Method)
I seem to have solved both the back button and orientation change problem.
The trick here is to not use onDestroyView()
, but to change the way the fragments are handled. instead of ft.attach(mFragment)
and ft.detach(mFragment)
, I changed them to ft.show(mFragment)
and ft.hide(mFragment)
.
As for the orientation change causing the app to crash, I believe (do correct me if I am wrong) that as long as you do not have an alternative landscape layout, you can add android:configChanges="orientation|screenSize"
to the manifest for this activity, like this:
<activity
android:theme="@style/AppTheme"
android:name="MyFragmentActivity"
android:label="@string/fragmentActivity"
android:configChanges="orientation|screenSize">
</activity>
这篇关于片段,地图应用程序崩溃时,后退按钮是pressed或者方向变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!