我正在编写一个有两种显示效果的应用: 1."电话模式"在正常大小的显示器上,一次显示一个片段(搜索片段,地图片段等)。这里的碎片加载没有特别的问题。 2。"平板电脑模式"在较大的显示器上,并排显示两个片段 - 一个与#34;电话模式相同",第二个是地图片段的永久显示。尝试在平板电脑模拟器上加载应用时会引发异常:
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中
&#34;电话模式&#34;:
<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>
和&#34;平板电脑模式&#34;
<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>
我非常感谢您提供的任何帮助......
更新
崩溃点位于marker = mMap.addMarker(markerOptions);
行的mapfragment末尾。我想我一定不能正确处理标记......仍然不清楚为什么它在单片段模式下工作正常,而不是双重片段。
答案 0 :(得分:0)
您正试图在onCreate()
中access UI elements但onCreate()
为时过早,无法调用getView()
,它将返回null。将需要触及片段视图层次结构的代码推迟到片段生命周期中的onCreateView()
或更高版本。因为片段视图可以在onCreateView()
方法中创建。
尝试包含onActivityCreated()
,当创建片段的活动并实例化此片段视图层次结构时调用它们。
答案 1 :(得分:0)
更新:已解决
问题最终出现在userIcon上(表示地图上显示的标记的美化类型)。当应用程序首次加载时,由于某种原因它返回0而不是null。因为它只是一个化妆品特征我只是删除,这解决了问题。不是最漂亮的解决方案,但它是我得到的解决方案,因为当应用程序的更关键部分仍然需要管理时,时间限制阻止我专注于更多时间。我希望它有所帮助。我希望一位经验丰富的程序员可能对标记系统非常熟悉,为那些希望包含自定义标记的人提供替代解决方案/解决方法。