2016-07-09 71 views
0

我正在寫一個應用程序,有兩種顯示: 1.「電話模式」在正常大小的顯示器上,一次顯示一個片段(搜索片段,地圖片段等)。這裏的碎片加載沒有特別的問題。 2.大型顯示屏上的「平板模式」,並排顯示兩個片段 - 一個與「手機模式」相同,第二個是地圖片段的永久顯示。當試圖加載在平板電腦模擬器應用程序,它拋出一個異常:NullPointerException在雙片段顯示

FATAL EXCEPTION: main 
Process: il.co.sredizemnomorie.myapiplaces, PID: 7808 
java.lang.RuntimeException: Unable to start activity ComponentInfo{il.co.sredizemnomorie.myapiplaces/il.co.sredizemnomorie.myapiplaces.MainActivity}: java.lang.NullPointerException 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245) 
at android.app.ActivityThread.access$800(ActivityThread.java:135) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196) 
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.NullPointerException 
at maps.f.g.a(Unknown Source) 
at maps.ag.g$a.<init>(Unknown Source) 
at maps.ag.g.a(Unknown Source) 
at maps.ag.R.<init>(Unknown Source) 
at maps.ag.t.a(Unknown Source) 
at uz.onTransact(:com.google.android.gms.DynamiteModulesB:167) 
at android.os.Binder.transact(Binder.java:361) 
at com.google.android.gms.maps.internal.IGoogleMapDelegate$zza$zza.addMarker(Unknown Source) 
at com.google.android.gms.maps.GoogleMap.addMarker(Unknown Source) 
at il.co.sredizemnomorie.myapiplaces.FragmentWithMap.setUpMap(FragmentWithMap.java:165) 
at il.co.sredizemnomorie.myapiplaces.FragmentWithMap.setUpMapIfNeeded(FragmentWithMap.java:141) 
at il.co.sredizemnomorie.myapiplaces.FragmentWithMap.onCreateView(FragmentWithMap.java:72) 
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974) 
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067) 
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252) 
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:742) 
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617) 
at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:339) 
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:602) 
at il.co.sredizemnomorie.myapiplaces.MainActivity.onStart(MainActivity.java:270) 
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171) 
at android.app.Activity.performStart(Activity.java:5241) 
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2168) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)  
at android.app.ActivityThread.access$800(ActivityThread.java:135)  
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)  
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)  

下面的代碼:

MainActivity.java

public class MainActivity extends ActionBarActivity implements FragmentWithDetails.OnFragmentInteractionListener, FragmentWithMap.OnFragmentInteractionListener, 
    FragmentWithDetails.ListFragmentListener, TextView.OnEditorActionListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, 
    SettingsFragment.OnFragmentInteractionListener { 

private static final String TAG = "PlaceFounder"; 
public static final String TAG_FAVORITES = "frag_favorites"; 
private static final String TAG_MAP = "map"; 
private static final String TAG_DETAILS = "details"; 


protected GoogleApiClient mGoogleApiClient; 
protected Location mLastLocation; 

private Bundle currentLocationBundle = new Bundle(); 
FragmentTransaction fragmentTransaction; 
private android.support.v4.app.FragmentManager fragmentManager; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    buildGoogleApiClient(); 

    fragmentManager = getSupportFragmentManager(); 

    FragmentWithDetails fragmentDetails; 
    if (isSingleFragment()) { 
     if (savedInstanceState == null) { 
      fragmentDetails = FragmentWithDetails.newInstance(); 
      fragmentDetails.setArguments(currentLocationBundle); 
      fragmentTransaction = fragmentManager.beginTransaction(); 
      fragmentTransaction.add(R.id.fragmnet_container, fragmentDetails, TAG_DETAILS); 
      fragmentTransaction.commit(); 
     } 
    }//end if we at small screen 
    else { 
     if (savedInstanceState == null) { 
      fragmentDetails = FragmentWithDetails.newInstance(); 
      FragmentWithMap fragmentWithMap = FragmentWithMap.newInstance(null); 
      fragmentDetails.setArguments(currentLocationBundle); 

      fragmentTransaction = fragmentManager.beginTransaction(); 
      fragmentTransaction.add(R.id.fragmnet_container_details, fragmentDetails, TAG_DETAILS); 
      fragmentTransaction.add(R.id.fragmnet_container_map, fragmentWithMap, TAG_MAP); 
      fragmentTransaction.commit(); 
     } 
    }//end if big screen 
} 


// Show favorites fragment 
private void showFavorites() { 
    currentLocationBundle.putInt("isShowFav", 1); 

    FragmentWithDetails fragmentFavorites = (FragmentWithDetails) fragmentManager.findFragmentByTag(TAG_FAVORITES); 
    if (fragmentFavorites == null) { 
     fragmentFavorites = FragmentWithDetails.newInstance(); 
     fragmentFavorites.setArguments(currentLocationBundle); 
    } 

    fragmentTransaction = fragmentManager.beginTransaction(); 
    fragmentTransaction.replace(R.id.fragmnet_container, fragmentFavorites, TAG_FAVORITES); 
    fragmentTransaction.addToBackStack(null); 
    fragmentTransaction.show(fragmentFavorites); 

    handleLargeLayout(); 

    fragmentTransaction.commit(); 
} 


//Hide details and map only on large screen 
//On small screen we reuse the same container 

private void handleLargeLayout() { 
    if (!isSingleFragment()) { 
     fragmentTransaction.hide(getDetailsFragment()); 
     fragmentTransaction.hide(getMapFragment()); 
    } 
} 

private FragmentWithMap getMapFragment() { 
    return (FragmentWithMap) fragmentManager.findFragmentByTag(TAG_MAP); 
} 

private FragmentWithDetails getDetailsFragment() { 
    return (FragmentWithDetails) fragmentManager.findFragmentByTag(TAG_DETAILS); 
} 

private FragmentWithDetails getFavoritesFragment() { 
    return (FragmentWithDetails) fragmentManager.findFragmentByTag(TAG_FAVORITES); 
} 


// Show settings fragment 

private void showSettings() { 
    SettingsFragment settingsFragment = SettingsFragment.newInstance(); 

    fragmentTransaction = fragmentManager.beginTransaction(); 
    fragmentTransaction.replace(R.id.fragmnet_container, settingsFragment, "frag_settings"); 
    fragmentTransaction.addToBackStack(null); 
    fragmentTransaction.show(settingsFragment); 
    handleLargeLayout(); 
    fragmentTransaction.commit(); 
} 


// Display current location on map 

private void getCurrentLocation() { 
    String currentLat = null; 
    String currentLong = null; 
    if (mLastLocation != null) { 
     currentLat = String.valueOf(mLastLocation.getLatitude()); 
     currentLong = String.valueOf(mLastLocation.getLongitude()); 
     if (getMapFragment() != null) { 
      getMapFragment().setPlace(new Place(0, "Current location", "", (float) mLastLocation.getLatitude(), (float) mLastLocation.getLongitude())); 
     } 

    } 
    currentLocationBundle.putString("currentLat", currentLat); 
    currentLocationBundle.putString("currentLong", currentLong); 
} 


//Builds a GoogleApiClient. 

protected synchronized void buildGoogleApiClient() { 
    mGoogleApiClient = new GoogleApiClient.Builder(this) 
      .addConnectionCallbacks(this) 
      .addOnConnectionFailedListener(this) 
      .addApi(LocationServices.API) 
      .build(); 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu 
    getMenuInflater().inflate(R.menu.menu_main, menu); 
    return true; 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 

    switch (item.getItemId()) { 
     case R.id.action_settings: 
      showSettings(); 
      return true; 
     case R.id.action_favorites: 
      showFavorites(); 
      return true; 
     default: 
      return super.onOptionsItemSelected(item); 
    } 
} 

protected boolean isSingleFragment() { 
    return findViewById(R.id.layout_single_fragment) != null; 
} 

@Override 
public void onFragmentInteraction(Uri uri) { 

} 

@Override 
public void onPlaceSelected(long placeId) { 
    fragmentManager = getSupportFragmentManager(); 
    Place place = getPlace(placeId); 

    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 
    if (isSingleFragment()) { 

     FragmentWithMap fragmentWithMap = FragmentWithMap.newInstance(place); 

     fragmentTransaction.replace(R.id.fragmnet_container, fragmentWithMap, TAG_MAP).addToBackStack(null); 
    } else { 
     if (getMapFragment() == null) { 
      android.support.v4.app.Fragment fragmentWithMap = FragmentWithMap.newInstance(place); 
      fragmentTransaction = fragmentManager.beginTransaction(); 
      fragmentTransaction.add(R.id.fragmnet_container_map, fragmentWithMap, TAG_MAP); 
      fragmentTransaction.show(fragmentWithMap); 
      fragmentTransaction.show(getDetailsFragment()); 

     } else { 

      FragmentWithMap fragmentWithMap = getMapFragment(); 
      fragmentTransaction.show(fragmentWithMap); 
      fragmentTransaction.show(getDetailsFragment()); 
      if (getFavoritesFragment() != null) { 
       fragmentTransaction.hide(getFavoritesFragment()); 
      } 

      fragmentWithMap.showPlace(place); 
     } 

    } 
    fragmentTransaction.commit(); 
} 


private Place getPlace(long placeId) { 
    Cursor cursor = null; 
    Place place = null; 
    try { 
     cursor = getContentResolver().query(PlacesContract.Places.CONTENT_URI, null, "_id=" + placeId, null, "name DESC"); 
     cursor.moveToNext(); 
     place = new Place(cursor.getInt(0), cursor.getString(1), cursor.getString(2), cursor.getFloat(3), cursor.getFloat(4)); 
    } finally { 
     if (cursor != null && !cursor.isClosed()) { 
      cursor.close(); 
     } 
    } 
    return place; 
} 

@Override 
public void onBackPressed() { 
    if (isSingleFragment() && getMapFragment() != null) { 
     fragmentManager.popBackStack(null, 
       FragmentManager.POP_BACK_STACK_INCLUSIVE); 
    } else if (fragmentManager.findFragmentByTag("frag_favorites") != null) { 
     fragmentManager.popBackStack(null, 
       FragmentManager.POP_BACK_STACK_INCLUSIVE); 
    } else if (fragmentManager.findFragmentByTag("frag_settings") != null) { 
     fragmentManager.popBackStack(null, 
       FragmentManager.POP_BACK_STACK_INCLUSIVE); 
    } else { 
     super.onBackPressed(); 
    } 

} 


@Override 
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 
    return true; 
} 

@Override 
protected void onStart() { 
    super.onStart(); 
    mGoogleApiClient.connect(); 

    //start google analytics 
    EasyTracker.getInstance(this).activityStart(this); // Add this method. 
} 

@Override 
protected void onStop() { 
    super.onStop(); 
    if (mGoogleApiClient.isConnected()) { 
     mGoogleApiClient.disconnect(); 
    } 

    //stop google analytics 
    EasyTracker.getInstance(this).activityStop(this); // Add this method. 
} 

/** 
* Runs when a GoogleApiClient object successfully connects. 
*/ 
@Override 
public void onConnected(Bundle connectionHint) { 

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 
     return; 
    } 
    mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); 
    if (mLastLocation == null) { 
     Toast.makeText(this, "Location not found", Toast.LENGTH_LONG).show(); 
    } 
    getCurrentLocation(); 
} 

@Override 
public void onConnectionFailed(ConnectionResult result) { 

    toast("No Google Service"); 
    Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode()); 
} 


private void toast(String message) { 
    Toast.makeText(this, message, 
      Toast.LENGTH_LONG).show(); 
} 

@Override 
public void onConnectionSuspended(int cause) { 
    // The connection to Google Play services was lost for some reason 
     Log.i(TAG, "Connection suspended"); 
    mGoogleApiClient.connect(); 
} 

}

的地圖片段:

FragmentWithMap.java

public class FragmentWithMap extends android.support.v4.app.Fragment { 
private OnFragmentInteractionListener mListener; 
private static final double LAT = 32.084; 
private static final double LON = 34.8878; 
Place place; 
private GoogleMap mMap; 
private View view; 
private Marker marker; 
int userIcon = FragmentWithDetails.userIcon; 

public static FragmentWithMap newInstance(Place place) { 
    Bundle args = new Bundle(); 
    if (place != null) { 
     args.putInt("id", place.getId()); 
     args.putString("name", place.getName()); 
     args.putString("address", place.getAddress()); 
     args.putFloat("lat", place.getLat()); 
     args.putFloat("lng", place.getLng()); 
    } 
    FragmentWithMap fragment = new FragmentWithMap(); 
    fragment.setArguments(args); 
    return fragment; 
} 

public FragmentWithMap() { 
    //empty public constructor 
} 


@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    if (getArguments() != null && getArguments().getString("name") != null) { 
     place = new Place(getArguments().getInt("id"), getArguments().getString("name"), 
       getArguments().getString("address"), getArguments().getFloat("lat"), 
       getArguments().getFloat("lng")); 
    } 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    if (view == null) { 
     view = inflater.inflate(R.layout.fragment_fragment_with_map, container, false); 
    } 
    setUpMapIfNeeded(); 
    return view; 
} 

@Override 
public void onDestroyView() { 
    super.onDestroyView(); 
    android.support.v4.app.Fragment f = getFragmentManager() 
      .findFragmentById(R.id.fragmnet_container_map); 
    if (f != null) { 
     try { 
      getFragmentManager().beginTransaction().remove(f).commit(); 
     } catch (IllegalStateException ise) { 
      Log.d("FragmentWithMap", "Already closed"); 
     } 
    } 

    ViewGroup parentViewGroup = (ViewGroup) view.getParent(); 
    if (parentViewGroup != null) { 
     parentViewGroup.removeAllViews(); 
    } 
} 

public void onButtonPressed(Uri uri) { 
    if (mListener != null) { 
     mListener.onFragmentInteraction(uri); 
    } 
} 

@Override 
public void onAttach(Activity activity) { 
    super.onAttach(activity); 
    try { 
     mListener = (OnFragmentInteractionListener) activity; 
    } catch (ClassCastException e) { 
     throw new ClassCastException(activity.toString() 
       + " must implement OnFragmentInteractionListener"); 
    } 
} 

@Override 
public void onDetach() { 
    super.onDetach(); 
    mListener = null; 
} 

public void showPlace(Place place) { 
    setPlace(place); 
    setUpMap(); 
} 

public void setPlace(Place place) { 
    this.place = place; 
} 


public interface OnFragmentInteractionListener { 
    public void onFragmentInteraction(Uri uri); 
} 

private void setUpMapIfNeeded() { 
    // Do a null check 
    if (mMap == null) { 
     // Try to obtain the map from the SupportMapFragment. 
     Fragment mmm = getChildFragmentManager().findFragmentById(R.id.fragment_map2); 
     mMap = ((SupportMapFragment) mmm).getMap(); 

     // Check if we were successful 
     if (mMap != null) { 
      setUpMap(); 
     } 
    } 
} 

private void setUpMap() { 
    double lat = LAT; 
    double lng = LON; 
    String name = "You are here"; 
    if (place != null) { 
     lat = place.getLat(); 
     lng = place.getLng(); 
     name = place.getName(); 
    } 
    if (marker != null) { 
     marker.remove(); 
    } 
    LatLng position = new LatLng(lat, lng); 
    MarkerOptions markerOptions = new MarkerOptions(). 
      position(position). 
      title(name). 
      icon(BitmapDescriptorFactory.fromResource(userIcon)). 
      snippet("Your last recorded location"); 

    marker = mMap.addMarker(markerOptions); 
    if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 
     return; 
    } 
    mMap.setMyLocationEnabled(true); 
    CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(position, 15); 
    mMap.animateCamera(cameraUpdate); 
} 

}

的個XML:

activity_main.xml中

「手機模式」:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools" 
android:id="@+id/layout_single_fragment" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:background="@android:color/darker_gray" 
android:paddingBottom="16dp" 
android:paddingLeft="16dp" 
android:paddingRight="16dp" 
android:paddingTop="16dp" 
tools:context=".MainActivity"> 

<FrameLayout 
    android:id="@+id/fragmnet_container" 
    android:layout_width="0dp" 
    android:layout_height="match_parent" 
    android:layout_weight="1"></FrameLayout> 

和 「平板模式」

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools" 
android:id="@+id/layout_two_fragments" 
android:layout_width="match_parent" 

android:layout_height="match_parent" 
android:background="@android:color/darker_gray" 
android:paddingBottom="16dp" 
android:paddingLeft="16dp" 
android:paddingRight="16dp" 
android:paddingTop="16dp" 
tools:context=".MainActivity" 

> 

<FrameLayout 
    android:id="@+id/fragmnet_container" 
    android:layout_width="wrap_content" 
    android:layout_height="match_parent"></FrameLayout> 

<FrameLayout 
    android:id="@+id/fragmnet_container_details" 
    android:layout_width="0dp" 
    android:layout_height="match_parent" 
    android:layout_weight="1.31"></FrameLayout> 

<FrameLayout 
    android:id="@+id/fragmnet_container_map" 
    android:layout_width="0dp" 
    android:layout_height="match_parent" 
    android:layout_weight="2"></FrameLayout> 

我會非常感謝您可能提供的任何幫助......

更新: 的crashpoint是在marker = mMap.addMarker(markerOptions);行的mapfragment末尾。我想我一定不能正確處理標記......仍然不清楚它爲什麼在單片段模式下工作正常,而不是雙片段。

回答

0

您正在嘗試access UI elements中的onCreate(),但onCreate()爲時過早致電getView()並且它將返回空值。推遲片段生命週期中需要觸及片段視圖層次的代碼爲onCreateView()或更高版本。由於在片段視圖中可以創建onCreateView()方法。

嘗試包括onActivityCreated(),它調用何時創建了片段的活動並且實例化了此片段視圖層次結構。

+0

感謝您的回覆,我會盡快嘗試!它也可能解決我遇到的其他一些問題......要清楚,OnCreate()的問題在MainActivity,MapFragment或兩者中? – Solmanian

0

更新:解決

問題結束了與userIcon(其表示在地圖上示出的標記的化妝品型)之中。當應用程序第一次加載時,它由於某種原因返回0而不是null。由於這只是一個美容功能,我只是將其刪除,並解決了問題。不是最漂亮的解決方案,但它是我得到的解決方案,因爲時間限制阻止我在此應用的更多關鍵部分仍需要維護時花更多時間來完成此任務;我希望它有幫助。我希望更有經驗的程序員可能對標記系統足夠熟悉,以便爲希望包含自定義標記的人提供替代解決方案/解決方法。