java - Android Java Google map 第二次加载时出错

标签 java android

MapPage.java类

    package com.example.cheng.freequeue;
    import android.app.Fragment;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.support.annotation.Nullable;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;

    import com.google.android.gms.maps.CameraUpdateFactory;
    import com.google.android.gms.maps.GoogleMap;
    import com.google.android.gms.maps.MapFragment;
    import com.google.android.gms.maps.OnMapReadyCallback;
    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 org.json.JSONArray;
    import org.json.JSONException;
    import org.json.JSONObject;

    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.util.ArrayList;

    public class MapPage extends Fragment implements GoogleMap.OnMarkerClickListener,OnMapReadyCallback {
        private GoogleMap mGoogleMap;
        private String address="myphpadress";
        private InputStream is=null;
        private String lat;
        private String lng;
        private String name;
        private Marker data;
        View myView;
        ArrayList<returnLatLng> list = null;
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
            myView = inflater.inflate(R.layout.activity_map_page, container, false);
            init();
            getJSON(address);
            list = new ArrayList<returnLatLng>();
            return myView;
}
public void init()
{
    MapFragment mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.mapFragment);
    mapFragment.getMapAsync(this);
}
/** Called when the map is ready. */
@Override
public void onMapReady(GoogleMap map) {
    mGoogleMap = map;
    mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(3.4496739,102.6010782),8.0f));



    // Set a listener for marker click.
    mGoogleMap.setOnMarkerClickListener(this);
}

/** Called when the user clicks a marker. */
@Override
public boolean onMarkerClick(final Marker marker) {

    // Retrieve the data from the marker.
    Integer clickCount = (Integer) marker.getTag();

    // Check if a click count was set, then display the click count.
    if (clickCount != null) {
        clickCount = clickCount + 1;
        marker.setTag(clickCount);
        //Toast.makeText(getActivity(), "Click!", Toast.LENGTH_SHORT).show();

    }

    // Return false to indicate that we have not consumed the event and that we wish
    // for the default behavior to occur (which is for the camera to move such that the
    // marker is centered and for the marker's info window to open, if it has one).
    return false;
}



//this method is actually fetching the json string
private void getJSON(final String urlWebService) {
    /*
    * As fetching the json string is a network operation
    * And we cannot perform a network operation in main thread
    * so we need an AsyncTask
    * The constrains defined here are
    * Void -> We are not passing anything
    * Void -> Nothing at progress update as well
    * String -> After completion it should return a string and it will be the json string
    * */
    class GetJSON extends AsyncTask<Void, Void, String> {

        //this method will be called before execution
        //you can display a progress bar or something
        //so that user can understand that he should wait
        //as network operation may take some time
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        //this method will be called after execution
        //so here we are displaying a toast with the json string
        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            try {
                getLatLng(s);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        //in this method we are fetching the json string
        @Override
        protected String doInBackground(Void... voids) {

            if(android.os.Debug.isDebuggerConnected())
                android.os.Debug.waitForDebugger();

            try {

                //creating a URL
                URL url = new URL(urlWebService);

                //Opening the URL using HttpURLConnection
                HttpURLConnection con = (HttpURLConnection) url.openConnection();

                //StringBuilder object to read the string from the service
                StringBuilder sb = new StringBuilder();

                //We will use a buffered reader to read the string from service
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(con.getInputStream()));

                //A simple string to read values from each line
                String json;

                //reading until we don't find null
                while ((json = bufferedReader.readLine()) != null) {

                    //appending it to string builder
                    sb.append(json + "\n");
                }

                //finally returning the read string
                return sb.toString().trim();
            } catch (Exception e) {
                return null;
            }

        }
    }

    //creating asynctask object and executing it
    GetJSON getJSON = new GetJSON();
    getJSON.execute();
}

private  void getLatLng(String json) throws JSONException {
    //creating a json array from the json string
    JSONArray jsonArray = new JSONArray(json);

    //creating a string array for listview

    list.clear();
    //looping through all the elements in json array
    for (int i = 0; i < jsonArray.length(); i++) {

        //getting json object from the json array
        JSONObject obj = jsonArray.getJSONObject(i);

        //getting the name from the json object and putting it inside string array
        lat = obj.getString("Latitude");
        lng=obj.getString("Longitude");
        name=obj.getString("company_name");
        Log.i("lat:", lat);
        Log.i("lng:", lng);
        Log.i("lng:", name);
        list.add(new returnLatLng(lat,lng,name));
        createMarker(Double.parseDouble(lat),Double.parseDouble(lng),name);

    }




}
protected Marker createMarker(double latitude, double longitude, String title) {

    return mGoogleMap.addMarker(new MarkerOptions()
            .position(new LatLng(latitude, longitude))
            .anchor(0.5f, 0.5f)
            .title(title)
    );
}
@Override
public void onDestroyView() {
    super.onDestroyView();
    MapFragment f = (MapFragment) getFragmentManager()
            .findFragmentById(R.id.mapFragment);
    if (f != null)
        getFragmentManager().beginTransaction().remove(f).commit();
}

}

Logcat 错误

    04-07 15:57:43.504 22910-22910/com.example.cheng.freequeue E/AndroidRuntime: FATAL EXCEPTION: main
 android.view.InflateException: Binary XML file line #0: Error inflating class fragment
     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:713)
     at android.view.LayoutInflater.rInflate(LayoutInflater.java:755)
     at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
     at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
     at com.example.cheng.freequeue.MapPage.onCreateView(MapPage.java:44)
     at android.app.Fragment.performCreateView(Fragment.java:1699)
     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:885)
     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1057)
     at android.app.BackStackRecord.run(BackStackRecord.java:682)
     at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1435)
     at android.app.FragmentManagerImpl$1.run(FragmentManager.java:441)
     at android.os.Handler.handleCallback(Handler.java:730)
     at android.os.Handler.dispatchMessage(Handler.java:92)
     at android.os.Looper.loop(Looper.java:137)
     at android.app.ActivityThread.main(ActivityThread.java:5166)
     at java.lang.reflect.Method.invokeNative(Native Method)
     at java.lang.reflect.Method.invoke(Method.java:525)
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:745)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:561)
     at dalvik.system.NativeStart.main(Native Method)
  Caused by: java.lang.IllegalArgumentException: Binary XML file line #0: Duplicate id 0x7f080070, tag null, or parent id 0xffffffff with another fragment for com.google.android.gms.maps.MapFragment
     at android.app.Activity.onCreateView(Activity.java:4811)
     at android.support.v4.app.BaseFragmentActivityApi14.onCreateView(BaseFragmentActivityApi14.java:41)
     at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:67)
     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:689)
     at android.view.LayoutInflater.rInflate(LayoutInflater.java:755) 
     at android.view.LayoutInflater.inflate(LayoutInflater.java:492) 
     at android.view.LayoutInflater.inflate(LayoutInflater.java:397) 
     at com.example.cheng.freequeue.MapPage.onCreateView(MapPage.java:44) 
     at android.app.Fragment.performCreateView(Fragment.java:1699) 
     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:885) 
     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1057) 
     at android.app.BackStackRecord.run(BackStackRecord.java:682) 
     at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1435) 
     at android.app.FragmentManagerImpl$1.run(FragmentManager.java:441) 
     at android.os.Handler.handleCallback(Handler.java:730) 
     at android.os.Handler.dispatchMessage(Handler.java:92) 
     at android.os.Looper.loop(Looper.java:137) 
     at android.app.ActivityThread.main(ActivityThread.java:5166) 
     at java.lang.reflect.Method.invokeNative(Native Method) 
     at java.lang.reflect.Method.invoke(Method.java:525) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:745) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:561) 
     at dalvik.system.NativeStart.main(Native Method) 

activity_map_page.xml

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.example.cheng.freequeue.MapPage">

        <fragment
            android:id="@+id/mapFragment"
            class="com.google.android.gms.maps.MapFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginBottom="0dp"
            android:layout_marginTop="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.294" />
    </android.support.constraint.ConstraintLayout>

有人可以帮助我吗?我已经尝试过 onDestroyView();将 android:name 替换为类并尝试并捕获方法,所有方法均来自 stackoverflow 解决方案,但仍然存在相同的问题。我已经运行调试我注意到这个

    myView = inflater.inflate(R.layout.activity_map_page, container, false);

第一次点击它运行没有问题,myView将从inflate中获取值。当我第二次点击运行 googleMap 时,虽然 inflate 中有相同的值,但 myView 将返回 null 并直接出现此错误:

   Binary XML file line #0: Error inflating class fragment

最佳答案

错误是因为,您正在其他 fragment 内膨胀 fragment 。这是Nested Fragment Documentation.

将布局更改为空容器。

<?xml version="1.0" encoding="utf-8"?> 
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mapFragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</LinearLayout>

然后在Fragment onViewCreated方法中:

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
FragmentManager fm = getChildFragmentManager();
SupportMapFragment mapFragment = (SupportMapFragment) fm.findFragmentByTag("mapFragment");
if (mapFragment == null) {
    mapFragment = new SupportMapFragment();
    FragmentTransaction ft = fm.beginTransaction();
    ft.add(R.id.mapFragmentContainer, mapFragment, "mapFragment");
    ft.commit();
    fm.executePendingTransactions();
  }
   mapFragment.getMapAsync(callback);
}

如果有帮助请告诉我。

关于java - Android Java Google map 第二次加载时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49705457/

相关文章:

java - 按下音量按钮时如何使通知静音?

android - 通过通知按钮播放流声音而无需打开应用

java - 定义命名空间标签以便生成的 XML 具有这些标签?

java - 方法创建新实例

java - Hadoop Writable和java.io.serialization有什么联系和区别?

java - 了解 java 中的二进制、字节流和字符

android - 在我的应用程序中显示图库图像

java - 在android中获取json时控制空值

java - 如何删除重复的 RecyclerView 适配器?

Java:这两个包装类语句之间的区别