过去两天我一直在阅读stackoverflow上的所有可能的线程,我无法弄清楚我的问题在哪里......每次我带来一个"修复&#34时遇到一个新的错误;
在代码之前,结束状态:我试图在多个片段之间设置导航抽屉。其中一个是餐馆搜索,以SupportMapFragment
显示搜索结果。
当我第一次加载包含地图的片段时,我没有收到错误,但是当我切换到另一个片段时,由于NavigationDrawer
而出现错误,当我发现错误时,我收到了错误消息。按下后退按钮,加上许多其他好东西。
这是我的代码:
NavigationDrawer.java
public class NavigationDrawerActivity extends FragmentActivity {
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;
private CharSequence mDrawerTitle;
private CharSequence mTitle;
private String[] mListFragments;
public static FragmentManager fragmentManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentManager = getSupportFragmentManager();
mTitle = mDrawerTitle = getTitle();
mListFragments = new String[] {"Search","Feed","About","Test"};
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) findViewById(R.id.left_drawer);
// set a custom shadow that overlays the main content when the drawer opens
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
// set up the drawer's list view with items and click listener
mDrawerList.setAdapter(new ArrayAdapter<String>(this,
R.layout.drawer_list_item, mListFragments));
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
// enable ActionBar app icon to behave as action to toggle nav drawer
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
// ActionBarDrawerToggle ties together the the proper interactions
// between the sliding drawer and the action bar app icon
mDrawerToggle = new ActionBarDrawerToggle(
this, /* host Activity */
mDrawerLayout, /* DrawerLayout object */
R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */
R.string.drawer_open, /* "open drawer" description for accessibility */
R.string.drawer_close /* "close drawer" description for accessibility */
) {
public void onDrawerClosed(View view) {
getActionBar().setTitle(mTitle);
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(mDrawerTitle);
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
if (savedInstanceState == null) {
selectItem(0);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.navigation_drawer, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// The action bar home/up action should open or close the drawer.
// ActionBarDrawerToggle will take care of this.
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle action buttons
switch(item.getItemId()) {
default:
return super.onOptionsItemSelected(item);
}
}
public void Logout(MenuItem item) {
SharedPreferences settings = getSharedPreferences(App.PREFS_NAME, 0);
settings.edit().remove("email").apply();
settings.edit().remove("password").apply();
settings.edit().remove("userID").apply();
settings.edit().putBoolean("hasLoggedIn",false).apply();
Intent intent = new Intent(this,LoginActivity.class);
startActivity(intent);
}
/* The click listner for ListView in the navigation drawer */
private class DrawerItemClickListener implements ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectItem(position);
}
}
Fragment fragment;
private void selectItem(int position) {
// update the main content by replacing fragments
switch (position){
// Search engine
// case 0:
// if ( fragment!=null) fragment.onDestroy();
// fragment = new RestaurantSearchFragment();
// break;
// Rating feed
case 1:
// fragment = new RatingFeedTabHostFragment();
// break;
// About screen
case 2:
fragment = new AboutFragment();
break;
case 3:
fragment = new RestaurantSearchFragment2();
break;
default:
fragment = new AboutFragment();
break;
}
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
setTitle(mListFragments[position]);
mDrawerLayout.closeDrawer(mDrawerList);
}
@Override
public void setTitle(CharSequence title) {
mTitle = title;
getActionBar().setTitle(mTitle);
}
/**
* When using the ActionBarDrawerToggle, you must call it during
* onPostCreate() and onConfigurationChanged()...
*/
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggls
mDrawerToggle.onConfigurationChanged(newConfig);
}
}
fragment_restaurant_search.xml
<!-- Your layouts-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<!--The content you want to add-->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_action_search_dark"
android:layout_gravity="center"
android:id="@+id/icon_search"/>
<AutoCompleteTextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:hint="Enter Restaurant Name"
android:id="@+id/restaurant_search"
android:completionThreshold="1"
android:imeOptions="actionSearch"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button_search"
android:text="Go!"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_action_location_found"
android:id="@+id/location_search_image"
android:layout_gravity="center"
/>
<EditText
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="Near Current Location"
android:singleLine="true"
android:imeOptions="actionSearch"
android:id="@+id/location_search"
android:inputType="none"/>
</LinearLayout>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="200dp"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"/>
<fragment android:name="com.bestpick.bestpickapplication.Screens.NavigationDrawer.RestaurantSearch.RestaurantsListFragment"
android:id="@+id/restaurant_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="@layout/fragment_restaurants"
/>
</LinearLayout>
RestaurantSearchFragment2.java
public class RestaurantSearchFragment2 extends Fragment
{
// Handles to UI widgets
private EditText locationSearchText;
private AutoCompleteTextView restaurantSearch;
private FragmentActivity context;
// sets context from calling Navigation Drawer Activity (FragmentActivity)
@Override
public void onAttach(Activity activity) {
context=(FragmentActivity) activity;
super.onAttach(activity);
}
public static FragmentManager fragmentManager;
private RestaurantMapFragment restaurantMapFragment;
private RestaurantsListFragment restaurantsListFragment;
@Override
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View view = inflater.inflate(R.layout.fragment_restaurant_search, container, false);
fragmentManager = getChildFragmentManager();
// setting up the restaurant list fragment
restaurantsListFragment = (RestaurantsListFragment) fragmentManager.findFragmentById(R.id.restaurant_fragment);
if (restaurantsListFragment == null) {
restaurantsListFragment = new RestaurantsListFragment();
fragmentManager.beginTransaction().replace(R.id.restaurant_fragment, restaurantsListFragment).commit();
}
// setting up the restaurant map fragment
restaurantMapFragment = (RestaurantMapFragment) fragmentManager.findFragmentById(R.id.map);
if (restaurantMapFragment==null){
restaurantMapFragment = new RestaurantMapFragment();
fragmentManager.beginTransaction().replace(R.id.map,restaurantMapFragment).commit();
}
return view;
}
}
RestaurantFragmentMap.java
public class RestaurantMapFragment extends Fragment {
private static View view;
/**
* Note that this may be null if the Google Play services APK is not
* available.
*/
private static GoogleMap mMap;
private static Double latitude, longitude;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (container == null) {
return null;
}
view = (RelativeLayout) inflater.inflate(R.layout.location_fragment, container, false);
// Passing harcoded values for latitude & longitude. Please change as per your need. This is just used to drop a Marker on the Map
latitude = 26.78;
longitude = 72.56;
setUpMapIfNeeded(); // For setting up the MapFragment
return view;
}
/***** Sets up the map if it is possible to do so *****/
public static void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the map.
if (mMap == null) {
// Try to obtain the map from the SupportMapFragment.
mMap = ((SupportMapFragment) NavigationDrawerActivity.fragmentManager
.findFragmentById(R.id.location_map)).getMap();
// Check if we were successful in obtaining the map.
if (mMap != null)
setUpMap();
}
}
/**
* This is where we can add markers or lines, add listeners or move the
* camera.
* <p>
* This should only be called once and when we are sure that {@link #mMap}
* is not null.
*/
private static void setUpMap() {
// For showing a move to my loction button
mMap.setMyLocationEnabled(true);
// For dropping a marker at a point on the Map
mMap.addMarker(new MarkerOptions().position(new LatLng(latitude, longitude)).title("My Home").snippet("Home Address"));
// For zooming automatically to the Dropped PIN Location
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude,
longitude), 12.0f));
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
if (mMap != null)
setUpMap();
if (mMap == null) {
// Try to obtain the map from the SupportMapFragment.
mMap = ((SupportMapFragment) NavigationDrawerActivity.fragmentManager
.findFragmentById(R.id.location_map)).getMap();
// Check if we were successful in obtaining the map.
if (mMap != null)
setUpMap();
}
}
@Override
public void onDetach() {
super.onDetach();
try {
Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
childFragmentManager.setAccessible(true);
childFragmentManager.set(this, null);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
/**** The mapfragment's id must be removed from the FragmentManager
**** or else if the same it is passed on the next time then
**** app will crash ****/
@Override
public void onDestroyView() {
super.onDestroyView();
if (mMap != null) {
RestaurantSearchFragment2.fragmentManager.beginTransaction()
.remove(RestaurantSearchFragment2.fragmentManager.findFragmentById(R.id.location_map)).commitAllowingStateLoss();
mMap = null;
}
}
}
location_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="@+id/location_map"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.SupportMapFragment" />
</RelativeLayout>
我遇到了世界上所有的错误,我现在最喜欢的是:
10-15 23:39:45.786 6568-6568/com.bestpick.bestpickapplication E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.bestpick.bestpickapplication, PID: 6568
java.lang.NullPointerException
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:651)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1484)
at android.support.v4.app.FragmentManagerImpl.dispatchDestroy(FragmentManager.java:1937)
at android.support.v4.app.Fragment.performDestroy(Fragment.java:1721)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1071)
at android.support.v4.app.FragmentManagerImpl.removeFragment(FragmentManager.java:1218)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:639)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1484)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:450)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
和
10-15 23:34:54.866 6251-6251/com.bestpick.bestpickapplication E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.bestpick.bestpickapplication, PID: 6251
java.lang.RuntimeException: Unable to destroy activity {com.bestpick.bestpickapplication/com.bestpick.bestpickapplication.Screens.NavigationDrawer.NavigationDrawerActivity}: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3497)
at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3515)
at android.app.ActivityThread.access$1400(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1249)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1360)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1378)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)
at com.bestpick.bestpickapplication.Screens.NavigationDrawer.RestaurantSearch.RestaurantMapFragment.onDestroyView(RestaurantMapFragment.java:120)
at android.support.v4.app.Fragment.performDestroyView(Fragment.java:1709)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1011)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1121)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1103)
at android.support.v4.app.FragmentManagerImpl.dispatchDestroyView(FragmentManager.java:1932)
at android.support.v4.app.Fragment.performDestroyView(Fragment.java:1706)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1011)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1121)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1103)
at android.support.v4.app.FragmentManagerImpl.dispatchDestroy(FragmentManager.java:1938)
at android.support.v4.app.FragmentActivity.onDestroy(FragmentActivity.java:336)
at android.app.Activity.performDestroy(Activity.java:5403)
at android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1117)
at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3484)
at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3515)
at android.app.ActivityThread.access$1400(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1249)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
我用Google搜索了所有内容,阅读了博客,stackoverflow ......仍然无法弄清楚任何事情!
感谢您的支持
答案 0 :(得分:0)
为背压做这个....
@Override
public void onBackPressed(){
android.support.v4.app.FragmentManager fm = this.getSupportFragmentManager();
if(fm.getBackStackEntryCount() > 0) {
fm.popBackStack();
}
else {
}
}