安卓 - android.view.InflateException: 二进制 XML 文件第8行:元素碎片解析错误

48
我正在开发一个应用程序,使用NavigationDrawer(导航抽屉),即DrawerLayout,并导航到不同的Fragments。当我调用一个Map_Fragment_Page 时,应用程序会崩溃,但第一次不会。第一次它可以正确地显示Map,但之后当我导航到不同的片段并再次返回Map_Fragment_Page时,就会崩溃,并显示一个错误:android.view.InflateException: Binary XML file line #8: Error inflating class fragment 我尝试了许多不同的解决方案,也在Google上搜索,但仍然没有得到所需的解决方案。问题还没有被解决。 howtoreach.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/howtoreach_map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.google.android.gms.maps.SupportMapFragment"/>

</RelativeLayout>

如何到达 HowToReach.java

    package com.demo.map.howtoreach;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import android.support.v4.app.Fragment;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;
import com.demo.map.R;

import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.Color;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

public class HowToReach extends Fragment
{
    public static final String TAG = "fragment_5";
    ProgressDialog dialog;

    GoogleMap googleMap;
    Marker marker;

    LocationManager locationManager;
    Location location;
    Criteria criteria;               
    String provider;

    double latitude, longitude;

    public HowToReach(){}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        final View v = inflater.inflate(R.layout.howtoreach, container, false);

        dialog = ProgressDialog.show(getActivity(),"","Loading",true,false);            

        int secondsDelayed = 4;
        new Handler().postDelayed(new Runnable()
                {
                    public void run()
        {               
            dialog.dismiss();
        }
        }, secondsDelayed * 1000);      

        try
        {
            // Loading map                  

            if (googleMap == null)
            {
                googleMap = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.howtoreach_map)).getMap();

                googleMap.setMyLocationEnabled(true);

                locationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);              
                criteria = new Criteria();               
                provider = locationManager.getBestProvider(criteria, true); 
                location = locationManager.getLastKnownLocation(provider);

                latitude = location.getLatitude();
                longitude = location.getLongitude();

                // create marker
                marker = googleMap.addMarker(new MarkerOptions().position(
                            new LatLng(latitude, longitude)).title("You are Here"));                  
                marker.setIcon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
                marker.showInfoWindow(); 

                CameraPosition cameraPosition = new CameraPosition.Builder().target(
                        new LatLng(latitude, longitude)).zoom(15).build();

                googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));                         

                Polyline line = googleMap.addPolyline(new PolylineOptions()
                        .add(new LatLng(latitude, longitude), new LatLng(18.520897,73.772396))
                        .width(2).color(Color.RED).geodesic(true));

                marker = googleMap.addMarker(new MarkerOptions().position(
                            new LatLng(18.520897, 73.772396)).title("DSK Ranwara Road"));             
                marker.setIcon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));

                // check if map is created successfully or not
                if (googleMap == null)
                {
                    Toast.makeText(getActivity(),"Sorry! unable to create maps", Toast.LENGTH_SHORT).show();
                }
            }

        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return v;

    }
}

你在测试哪个版本? - user3110424
操作系统版本还是地图版本? - Mitesh Shah
2
4.0.4 冰淇淋三明治。三星S DUOS。我猜这不是问题所在,因为地图第一次加载时,当我从其他片段导航回地图页面时,它会崩溃... - Mitesh Shah
你调试过你的代码吗?尝试在onResume方法中编写//加载地图代码。 - user3110424
实际上,问题在于您正在检查 if(googleMap == null) { //your current code},而您没有指定 if(googleMap != null) {marker = googleMap.addMarker(new MarkerOptions().position( new LatLng(latitude, longitude)).title("You are Here"));}。请尝试像这样实现。 - user3110424
显示剩余4条评论
12个回答

64
Yes.. I want Map inside a Fragment.
你应该使用一个 MapViewhttp://developer.android.com/reference/com/google/android/gms/maps/MapView.html
public class HowToReach  extends Fragment {
    MapView mapView;
    GoogleMap map;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment2, container, false);
        // Gets the MapView from the XML layout and creates it

        try {
            MapsInitializer.initialize(getActivity());
        } catch (GooglePlayServicesNotAvailableException e) {
            Log.e("Address Map", "Could not initialize google play", e);
        }

        switch (GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity()) )
        {
            case ConnectionResult.SUCCESS:
                Toast.makeText(getActivity(), "SUCCESS", Toast.LENGTH_SHORT).show();
                mapView = (MapView) v.findViewById(R.id.map);
                mapView.onCreate(savedInstanceState);
                // Gets to GoogleMap from the MapView and does initialization stuff
                if(mapView!=null)
                {
                    map = mapView.getMap();
                    map.getUiSettings().setMyLocationButtonEnabled(false);
                    map.setMyLocationEnabled(true);
                    CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(new LatLng(43.1, -87.9), 10);
                    map.animateCamera(cameraUpdate);
                }
                break;
            case ConnectionResult.SERVICE_MISSING: 
                Toast.makeText(getActivity(), "SERVICE MISSING", Toast.LENGTH_SHORT).show();
                break;
            case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED: 
                Toast.makeText(getActivity(), "UPDATE REQUIRED", Toast.LENGTH_SHORT).show();
                break;
            default: Toast.makeText(getActivity(), GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity()), Toast.LENGTH_SHORT).show();
        }




        // Updates the location and zoom of the MapView

        return v;
    }

    @Override
    public void onResume() {
        mapView.onResume();
        super.onResume();
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        mapView.onDestroy();
    }
    @Override
    public void onLowMemory() {
        super.onLowMemory();
        mapView.onLowMemory();
    }
}

fragment2.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">

    <com.google.android.gms.maps.MapView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/map" />

</RelativeLayout>

更新:

https://developers.google.com/android/reference/com/google/android/gms/maps/MapView#public-constructors

getMap() 被弃用,请使用 getMapAsync(OnMapReadyCallback)。回调方法会提供一个 GoogleMap 实例,并保证该实例非空且可以立即使用。


代码错误:在第mapView.onCreate(savedInstanceState);行。 - Mitesh Shah
9
@Mitesh 我不是你的调试器,请自己调试代码。但这是做法,剩下的修改由你决定。 - Raghunandan
mapView为空。它未被正确初始化。 - Raghunandan
解决了...谢谢..其实你是对的...但我很紧张..而且正在处理实时项目,所以向你求助.. :) - Mitesh Shah
2
@Raghunandan 地图加载需要很长时间,你遇到过这种问题吗? - Snehal Poyrekar
显示剩余13条评论

10

所以,如果在第二次打开片段后它崩溃了。 你只需要在OnDestroy中添加以下内容。

@Override
public void onDestroy() {
    super.onDestroy();
    getFragmentManager().beginTransaction().remove(mapfragmentnamehere).commit();
}

如果使用支持碎片,请进行必要的更改。


它在remove方法上报错,因为它无法转换为MapFragment。 - Trideep
这解决了我的问题,谢谢先生!代码 onDestroy: MapFragment mapFragment = (MapFragment)getFragmentManager().findFragmentById(R.id.map); getFragmentManager().beginTransaction().remove(mapFragment).commit(); - user497849

8

我的经验是通过使用 XML 标记添加的片段实现的。

<fragment>...</fragment>.

这些片段通常是嵌套的,并且在父片段被销毁时不会被销毁。一旦您再次尝试膨胀它们,您会收到异常,该异常基本上抱怨已经膨胀了此片段。因此,一旦父片段被销毁,我就手动销毁我的嵌套片段。只需使用以下代码片段并根据需要进行调整。此代码位于具有嵌套片段作为xml标记的父片段中。

@Override
public void onDestroy() {
    super.onDestroy();
    final FragmentManager fragManager = this.getFragmentManager();
    final Fragment fragment = fragManager.findFragmentById(/*id of fragment*/);
    if(fragment!=null){
        fragManager.beginTransaction().remove(fragment).commit();
    }
}

动态创建片段没有任何问题。动态的意思是:你没有使用片段XML标记。
希望这可以帮助你!祝编程愉快!

4
我把这个放在我的片段中。
@Override
public void onPause() {
    super.onPause();

    getChildFragmentManager().beginTransaction()
            .remove(mMapFragment)
            .commit();
}

它可以在不替换MapView的情况下工作。


1

在你的课堂上


    View mTrackView = inflater.inflate(R.layout.mylayout, container, false);
    SupportMapFragment mSupportMapFragment = SupportMapFragment.newInstance();
    FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
    fragmentTransaction.add(R.id.mapwhere, mSupportMapFragment);
    fragmentTransaction.commit();

    if(mSupportMapFragment!=null){

        googleMap = mSupportMapFragment.getMap();
        if(googleMap!=null){
        googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
        googleMap.getUiSettings().setMyLocationButtonEnabled(false);
        googleMap.setMyLocationEnabled(false);
        if (mgpr_tracker.canGetLocation())
            CURREN_POSITION = new LatLng(mgpr_tracker.getLatitude(),
                    mgpr_tracker.getLongitude());

        CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(
                CURREN_POSITION, ZOOM_LEVEL);
        googleMap.animateCamera(cameraUpdate);
          }
        }

mylayout.xml


<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:map="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical" >
 <FrameLayout
   android:layout_width="match_parent"
   android:layout_height="0dp"
   android:layout_weight="1.03"

   android:id="@+id/mapwhere" />


  <TextView
   android:layout_width="match_parent"
   android:layout_height="wrap_content"/>

</LinearLayout>

getChildFragmentManager() 无法解析为类型,同时将API升级到17..有什么解决方案? - Joseph Mekwan

1
将此更改
googleMap = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.howtoreach_map)).getMap();

googleMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.howtoreach_map)).getMap();

为了做到这一点,我需要扩展FragmentActivity而不是Fragment。而且由于我要从上一个页面调用此片段,因此无法使用FragmentActivity。 - Mitesh Shah
@Mitesh,你想让你的应用程序在哪个API级别上运行?在清单文件中,你的最小SDK是多少?托管片段的活动必须扩展FragmentActivity。 - Raghunandan
@Raghunandan,我不太懂你的意思。你能否分享一个链接来说明它在哪里有记录?如果可能,也请提供一个好的Fragment教程,谢谢 :-) - user3110424
如果您的min sdk是11,那么您可以使用SupportMapFragment,此时您的activity应该继承自FragmentActivity。您可以查看片段文档以及如何在api级别低于11的情况下使用片段。 - Raghunandan
@Raghunandan 我的MapFragmentPage扩展自Fragment而不是Activity。如果我将其扩展为Activity,那么我如何从扩展FragmentActivity的MainClass中调用它? - Mitesh Shah
显示剩余5条评论

0

当我有一个ViewPager时,我将其放在我的Fragment中:

@Override
public void onPause() {
    Fragment fragment = (getChildFragmentManager().findFragmentById(R.id.fragment_map_map));
    FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
    ft.remove(fragment);
    ft.commit();
    super.onPause();
}

0

检查是否具有精确的清单权限。我没有在清单中包含以下权限,这导致了此错误。

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

请在您的清单文件中包含以下权限:
<!-- - THIS IS THE USER PERMISSION FOR GETTING LATITUDE AND LONGTITUDE FROM INTERNET -->      
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" /> 
 <uses-permission android:name="android.permission.READ_PHONE_STATE" />
 <uses-permission android:name="android.permission.GET_ACCOUNTS" /> 
 <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
 <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS"/>
 <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>

0

由于您第一次告诉我您的代码可以工作,所以我认为当您再次调用地图时,您的googlemap对象不是null,并且您没有正确处理它,请尝试在您的代码中实现以下内容。

if (googleMap == null) {
// Your code 
} else if(googleMap != null) {
     marker = googleMap.addMarker(new MarkerOptions().position(new LatLng(18.520897, 73.772396)).title("DSK Ranwara Road"));
}

不行...同样的错误..在Java文件的第52行..即final View v = inflater.inflate(R.layout.howtoreach, container, false); - Mitesh Shah
请参考以下链接:https://dev59.com/K27Xa4cB1Zd3GeqPo1o1 - user3110424
抱歉伙计...没有解决方案..地图第一次加载后就崩溃了..你提供的解决方案是“当地图第一次崩溃时”。 - Mitesh Shah
你的Fragment中有使用构造函数吗?请仔细跟随我提供的链接。 - user3110424

0

我收到了相同的错误信息:

对我来说原因很简单:重新创建了一个视图

public View onCreateView(
        LayoutInflater inflater,
        ViewGroup container,
        Bundle savedInstanceState){
    super.onCreateView(inflater,container,savedInstanceState);
    self_view=inflater.inflate(R.layout.fragment_player,container,false);
    return self_view;
    }

onCreateView 可能会被多次调用。

当发生这种情况时,上述代码会在旧视图仍然存在的情况下为片段创建一个新视图。

该错误会在某些适配器中弹出,而在另一些适配器中则不会;在我的情况下,FragmentStatePagerAdapter 很好用,而 FragmentPagerAdapter 则很难用,因为前者会销毁其片段,而后者则会重复使用它们。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接