سؤال

I am currently developing an app for Android that uses the Google Maps API v2. I am showing custom markers from an external XML file: http://dds.orgfree.com/DDS/landmarks_genxmlv2.php , which will show some landmarks in the map.

As you can see in my code below, I am using StrictMode to avoid NetworkOnMainThreadException while testing this app in an actual phone. I know that it is not advisable to used this method. It should be done in a separate thread and in background through AsyncTask. I tried implementing AsyncTask in this app but I have no luck. Can anyone help me to furnish my code or give some good suggestions that will help me with this? Thanks a lot in advance.

public class MapViewActivity extends android.support.v4.app.FragmentActivity {

    static final LatLng CITYHALL = new LatLng(07.0644444, 125.6077778);
    private GoogleMap mMap;

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

        setUpMapIfNeeded();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.mapview_options_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.normal_mapstyle) {
            mMap.setMapType(MAP_TYPE_NORMAL);
        } else if (item.getItemId() == R.id.hybrid_mapstyle) {
            mMap.setMapType(MAP_TYPE_HYBRID);
        } else if (item.getItemId() == R.id.satellite_mapstyle) {
            mMap.setMapType(MAP_TYPE_SATELLITE);
        } else if (item.getItemId() == R.id.terrain_mapstyle) {
            mMap.setMapType(MAP_TYPE_TERRAIN);
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onResume() {
        super.onResume();
        setUpMapIfNeeded();
    }

    private void setUpMapIfNeeded() {

        if (mMap == null) {
            // Try to obtain the map from the SupportMapFragment.
            mMap = ((SupportMapFragment) getSupportFragmentManager()
                    .findFragmentById(R.id.map)).getMap();
            // Check if we were successful in obtaining the map.
            if (mMap != null) {
                setUpMap();
            }
        }
    }

    private void setUpMap() {

        Document doc = null;
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory
                    .newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            doc = builder
                    .parse("http://dds.orgfree.com/DDS/landmarks_genxmlv2.php");
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        NodeList markers = doc.getElementsByTagName("marker");

        try {
            for (int i = 0; i < markers.getLength(); i++) {
                Element item = (Element) markers.item(i);
                String name = item.getAttribute("name");
                String address = item.getAttribute("address");
                String stringLat = item.getAttribute("lat");
                String stringLng = item.getAttribute("lng");
                String icon = item.getAttribute("icon");
                Double lat = Double.valueOf(stringLat);
                Double lng = Double.valueOf(stringLng);

                mMap = ((SupportMapFragment) getSupportFragmentManager()
                        .findFragmentById(R.id.map)).getMap();

                mMap.addMarker(new MarkerOptions()
                        .position(new LatLng(lat, lng))
                        .title(name)
                        .snippet(address)
                        .icon(BitmapDescriptorFactory.fromAsset(new String(icon
                                + ".png"))));

                // Move the camera instantly to City Hall with a zoom of 15.
                mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(CITYHALL, 15));
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
    }
}

Here's what I have tried.

public class MapViewActivity extends android.support.v4.app.FragmentActivity {

    static final LatLng CITYHALL = new LatLng(07.0644444, 125.6077778);
    private GoogleMap mMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_mapview);
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
                .permitAll().build();

        StrictMode.setThreadPolicy(policy);
        setUpMapIfNeeded();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.mapview_options_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.map_menu_showlegend) {
            Log.d("MENU", "Show Legend was CLICKED!");
        } else if (item.getItemId() == R.id.map_menu_maptype) {
            Log.d("MENU", "Map Type was CLICKED!");
        } else if (item.getItemId() == R.id.normal_mapstyle) {
            Log.d("MENU", "MAP_TYPE_NORMAL was CLICKED!");
            mMap.setMapType(MAP_TYPE_NORMAL);
        } else if (item.getItemId() == R.id.hybrid_mapstyle) {
            Log.d("MENU", "MAP_TYPE_HYBRID was CLICKED!");
            mMap.setMapType(MAP_TYPE_HYBRID);
        } else if (item.getItemId() == R.id.satellite_mapstyle) {
            Log.d("MENU", "MAP_TYPE_SATELLITE was CLICKED!");
            mMap.setMapType(MAP_TYPE_SATELLITE);
        } else if (item.getItemId() == R.id.terrain_mapstyle) {
            Log.d("MENU", "MAP_TYPE_TERRAIN was CLICKED!");
            mMap.setMapType(MAP_TYPE_TERRAIN);
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onResume() {
        super.onResume();
        setUpMapIfNeeded();
    }

    private void setUpMapIfNeeded() {
        // Do a null check to confirm that we have not already instantiated the
        // map.
        if (mMap == null) {
            // Try to obtain the map from the SupportMapFragment.
            mMap = ((SupportMapFragment) getSupportFragmentManager()
                    .findFragmentById(R.id.map)).getMap();
            // Check if we were successful in obtaining the map.
            if (mMap != null) {
                setUpMap();
            }
        }
    }

    private Boolean isOnline() {
        ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo ni = cm.getActiveNetworkInfo();
        if (ni != null && ni.isConnected())
            return true;

        return false;
    }

    private void setUpMap() {
        new ParseXML().execute();
    }

    private class ParseXML extends AsyncTask<Void, Void, Document> {
        Document doc = null;

        @Override
        protected Document doInBackground(Void... params) {

            try {
                Thread.sleep(2000);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }

            if (isOnline()) {

                try {
                    DocumentBuilderFactory factory = DocumentBuilderFactory
                            .newInstance();
                    DocumentBuilder builder = factory.newDocumentBuilder();
                    doc = builder
                            .parse("http://dds.orgfree.com/DDS/landmarks_genxmlv2.php");
                } catch (ParserConfigurationException e) {
                    e.printStackTrace();
                } catch (SAXException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

                NodeList markers = doc.getElementsByTagName("marker");

                try {
                    for (int i = 0; i < markers.getLength(); i++) {
                        Element item = (Element) markers.item(i);
                        String name = item.getAttribute("name");
                        String address = item.getAttribute("address");
                        String stringLat = item.getAttribute("lat");
                        String stringLng = item.getAttribute("lng");
                        String icon = item.getAttribute("icon");
                        Double lat = Double.valueOf(stringLat);
                        Double lng = Double.valueOf(stringLng);

                        mMap = ((SupportMapFragment) getSupportFragmentManager()
                                .findFragmentById(R.id.map)).getMap();

                        mMap.addMarker(new MarkerOptions()
                                .position(new LatLng(lat, lng))
                                .title(name)
                                .snippet(address)
                                .icon(BitmapDescriptorFactory
                                        .fromAsset(new String(icon + ".png"))));

                        // Move the camera instantly to City Hall with a zoom of
                        // 15.
                        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
                                CITYHALL, 15));
                    }
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                }
            } else {
                Toast.makeText(MapViewActivity.this, "No connection..",
                        Toast.LENGTH_LONG).show();
            }

            return doc;
        }

        @Override
        protected void onPostExecute(Document doc) {
            super.onPostExecute(doc);
        }
    }
}
هل كانت مفيدة؟

المحلول

You cannot change UI from background thread.
Therefore move everything that changes UI to onPostExecute() method.
I already answered today the same question with code example : Android disable button on successful doinbackground call

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top