Android - android.view.InflateException: двоичная строка XML файла # 8: ошибка раздувания фрагмента класса
Я разрабатываю приложение, используя NavigationDrawer
i.e. 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;
}
}
Ответы
Ответ 1
Yes.. I want Map inside a Fragment.
Вы должны использовать MapView
http://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>
Update:
https://developers.google.com/android/reference/com/google/android/gms/maps/MapView#public-constructors
getMap()
устарел. Вместо этого используйте getMapAsync(OnMapReadyCallback)
. Метод обратного вызова предоставляет экземпляр GoogleMap, который должен быть не нулем и готов к использованию.
Ответ 2
Итак, если он сработает после открытия фрагмента второй раз.
Все, что вам нужно, это в OnDestroy
@Override
public void onDestroy() {
super.onDestroy();
getFragmentManager().beginTransaction().remove(mapfragmentnamehere).commit();
}
Сделайте необходимые изменения, если вы используете фрагмент поддержки
Ответ 3
Мой опыт, сделанный с фрагментами, добавленными 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.
Ответ 5
Измените это
googleMap = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.howtoreach_map)).getMap();
к
googleMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.howtoreach_map)).getMap();
Ответ 6
В вашем классе
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>
Ответ 7
Как вы говорите в первый раз, когда ваш код работает, поэтому я думаю, что когда вы снова назовете свою карту, ваш объект 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"));
}
Ответ 8
Проверьте, есть ли у вас точное разрешение манифеста. Я не включил нижеприведенное разрешение в манифест, и он дал эту ошибку.
<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"/>
Ответ 9
Я помещаю это в свой фрагмент, когда у меня есть viewpager:
@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();
}
Ответ 10
Чтобы Google API v2 работал (я также использую SupportMapFragment), вы должны включить эти разрешения
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-feature android:glEsVersion="0x00020000" android:required="true"/>
Надеюсь, это поможет вам, ребята.
P.S Я использовал эти разрешения для добавления простой карты в свое приложение. Существуют и другие разрешения, которые указывает на эту ссылку.
Ответ 11
Я получил такое же сообщение об ошибке:
Причиной для меня было просто: воссоздать представление
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 был убийственным, потому что прежний уничтожил его фрагменты, а последний использовал их повторно.
Ответ 12
Как я исправил свою проблему после многого поиска, Поместите эти строки внутри фрагмента в метод Pause.
@Override
public void onPause() {
super.onPause();
final FragmentManager fragManager = this.getChildFragmentManager();
final Fragment fragment = fragManager.findFragmentById(R.id.map);
if(fragment!=null){
fragManager.beginTransaction().remove(fragment).commit();
googleMap=null;
}
}
Обязательно null googlemap.
Нет необходимости использовать MapView, вы можете сделать это, не используя MapView