使用JSON并为Android Maps API加载时间创建标记



我正在我的android项目中实现谷歌地图,该项目从URL中检索JSON数据以在地图中绘制标记,它还具有自动完成谷歌位置地址的搜索选项。API这里是我的代码。

import android.content.Context;
import android.content.Intent;
import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
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.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class MapsActivity extends FragmentActivity implements AdapterView.OnItemClickListener {
LocationAddress add=new LocationAddress();
DashboardActivity dObj=new DashboardActivity();
public void onClickHome (View v)
{
final Intent intent = new Intent(getApplicationContext(), DashboardActivity.class);
startActivity(intent);
}
class MyInfoWindowAdapter implements GoogleMap.InfoWindowAdapter {
private final View myContentsView;
MyInfoWindowAdapter(){
myContentsView = getLayoutInflater().inflate(R.layout.custom_info_contents, null);
}
@Override
public View getInfoContents(Marker arg0) {
displayView(arg0);
return myContentsView;
}
@Override
public View getInfoWindow(Marker arg0) {
return null;
}
public void displayView(Marker arg0) {
String[] contents=arg0.getTitle().split("@");
String title=contents[0];
String address=contents[1];
((TextView)myContentsView.findViewById(R.id.title)).setText(title);
((TextView)myContentsView.findViewById(R.id.snippet)).setText(address);
}
}
private static final String LOG_TAG = "myApp";
private static final String SERVICE_URL = "JSON_DATA_URL";
private static final String PLACES_API_BASE = "https://maps.googleapis.com/maps/api/place";
private static final String TYPE_AUTOCOMPLETE = "/autocomplete";
private static final String OUT_JSON = "/json";
//------------ make your specific key ------------
private static final String API_KEY = "AIzaSyDKUpzHkox5q5-pcNYmRS-UT7izEvd6WtQ";
protected GoogleMap map;
private GoogleApiClient client;
TextView latlongLocation;
Marker marker;
Button clear;
AutoCompleteTextView autoCompView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
setUpMapIfNeeded();
setTitleFromActivityLabel(R.id.title_text);
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
autoCompView = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView);
autoCompView.setAdapter(new GooglePlacesAutocompleteAdapter(this, R.layout.list_item));
autoCompView.setOnItemClickListener(this);
clear=(Button)findViewById(R.id.clear);
clear.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
autoCompView.setText("");
}
});
}

public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
String str = (String) adapterView.getItemAtPosition(position);
Geocoder geocoder = new Geocoder(getApplicationContext());
List<Address> addresses = null;
try
{
//   removeSearchMarker();
addresses = geocoder.getFromLocationName(str, 3);
if (addresses != null && !addresses.equals(""))
search(addresses);
}
catch (Exception e) {
}
}
public static ArrayList<String> autocomplete(String input) {
ArrayList<String> resultList = null;
HttpURLConnection conn = null;
StringBuilder jsonResults = new StringBuilder();
try {
StringBuilder sb = new StringBuilder(PLACES_API_BASE + TYPE_AUTOCOMPLETE + OUT_JSON);
sb.append("?key=" + API_KEY);
sb.append("&language" + "fa");
sb.append("&components=country:af");
sb.append("&input=" + URLEncoder.encode(input, "utf8"));
URL url = new URL(sb.toString());
System.out.println("URL: "+url);
conn = (HttpURLConnection) url.openConnection();
InputStreamReader in = new InputStreamReader(conn.getInputStream());
int read;
char[] buff = new char[1024];
while ((read = in.read(buff)) != -1) {
jsonResults.append(buff, 0, read);
}
} catch (MalformedURLException e) {
Log.e(LOG_TAG, "Error processing Places API URL", e);
return resultList;
} catch (IOException e) {
Log.e(LOG_TAG, "Error connecting to Places API", e);
return resultList;
} finally {
if (conn != null) {
conn.disconnect();
}
}
try {
JSONObject jsonObj = new JSONObject(jsonResults.toString());
JSONArray predsJsonArray = jsonObj.getJSONArray("predictions");
resultList = new ArrayList<String>(predsJsonArray.length());
for (int i = 0; i < predsJsonArray.length(); i++) {
System.out.println(predsJsonArray.getJSONObject(i).getString("description"));
System.out.println("============================================================");
resultList.add(predsJsonArray.getJSONObject(i).getString("description"));
}
} catch (JSONException e) {
Log.e(LOG_TAG, "Cannot process JSON results", e);
}
return resultList;
}
class GooglePlacesAutocompleteAdapter extends ArrayAdapter<String> implements Filterable {
private ArrayList<String> resultList;
public GooglePlacesAutocompleteAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
}
@Override
public int getCount() {
return resultList.size();
}
@Override
public String getItem(int index) {
return resultList.get(index);
}
@Override
public Filter getFilter() {
Filter filter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if (constraint != null) {
resultList = autocomplete(constraint.toString());
filterResults.values = resultList;
filterResults.count = resultList.size();
}
return filterResults;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results != null && results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
};
return filter;
}
}
protected void search(List<Address> addresses) {
Address address = (Address) addresses.get(0);
LatLng latLng = new LatLng(address.getLatitude(), address.getLongitude());
// String  addressText = String.format("%s, %s", address.getMaxAddressLineIndex() > 0 ? address.getAddressLine(0) : "", address.getCountryName());
map.moveCamera(CameraUpdateFactory.newLatLng(latLng));
map.animateCamera(CameraUpdateFactory.zoomTo(14));
latlongLocation.setText("Latitude:" + address.getLatitude() + ", Longitude:" + address.getLongitude());
// map.setInfoWindowAdapter(new MyInfoWindowAdapter());
}
@Override
protected void onResume() {
super.onResume();
setUpMapIfNeeded();
}
@Override
protected void onPause() {
setUpMapIfNeeded();
super.onPause();
}
@Override
protected void onRestart() {
setUpMapIfNeeded();
super.onRestart();
}
@Override
protected void onDestroy() {
map=null;
super.onDestroy();
}

private void setUpMapIfNeeded() {
if (map == null) {
map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
.getMap();
if (map != null) {
setUpMap();
}
}
}
private void setUpMap() {
LatLng origin = new LatLng(34.520299, 69.179912);
CameraUpdate panToOrigin = CameraUpdateFactory.newLatLng(origin);
map.moveCamera(panToOrigin);
map.animateCamera(CameraUpdateFactory.zoomTo(13), 400, null);
map.getUiSettings();
map.getUiSettings().setZoomControlsEnabled(true);
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
map.setMyLocationEnabled(true);
map.setInfoWindowAdapter(new MyInfoWindowAdapter());
new Thread(new Runnable() {
public void run() {
try {
retrieveLocations();
} catch (IOException e) {
Log.e(LOG_TAG, "Cannot retrive locations", e);
return;
}
}
}).start();
}
protected void retrieveLocations() throws IOException {
HttpURLConnection conn = null;
final StringBuilder json = new StringBuilder();
try {
URL url = new URL(SERVICE_URL);
conn = (HttpURLConnection) url.openConnection();
InputStreamReader in = new InputStreamReader(conn.getInputStream());
int read;
char[] buff = new char[1024];
while ((read = in.read(buff)) != -1) {
json.append(buff, 0, read);
}
} catch (IOException e) {
Log.e(LOG_TAG, "Error connecting to service", e);
throw new IOException("Error connecting to service", e);
} finally {
if (conn != null) {
conn.disconnect();
}
}
runOnUiThread(new Runnable() {
public void run() {
try {
createMarkersFromJson(json.toString());
} catch (JSONException e) {
Log.e(LOG_TAG, "Error processing JSON", e);
}
}
});
}
void createMarkersFromJson(String json) throws JSONException {
JSONArray jsonArray = new JSONArray(json);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObj = jsonArray.getJSONObject(i);
String address=add.getAddressFromLocation(jsonObj.getDouble("geolat"), jsonObj.getDouble("geolng"), getApplicationContext());
String date=jsonObj.getString("posted_date");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date testDate=null;
try{
testDate=sdf.parse(date);
}catch (Exception ex){
ex.printStackTrace();
}
sdf=new SimpleDateFormat("EEE, d MMM yyyy  HH:mm aa");
date=sdf.format(testDate);
map.addMarker(new MarkerOptions()
.title(address.toString()+"@"+date)
.position(new LatLng(jsonObj.getDouble("geolat"), jsonObj.getDouble("geolng")
))
.icon(BitmapDescriptorFactory.fromResource(R.drawable.icon3))
);
}
}
public void setTitleFromActivityLabel (int textViewId)
{
TextView tv = (TextView) findViewById (textViewId);
if (tv != null) tv.setText (getTitle ());
}
}

这些代码可以正确地从地图中的json数据中绘制标记,但问题是,当我开始此活动时,显示地图和标记需要太多时间,在这段时间里,一切都像冻结了一样,我无法返回或回家,如果我在任何screan组件上多次单击,应用程序就会崩溃

createMarkersFromJson方法为创建标记而循环通过的json记录的数量可能像40-50条记录,并且有扩展的可能性。所以我的问题是这个问题的原因是什么?有没有其他方法可以在不破坏应用程序的情况下快速显示地图中的标记

我应该提到的是,我是android开发的新手,任何帮助都将不胜感激。提前感谢!

根据Android指南,我认为您应该使用AsyncTask进行"retrieveLocations",而不是自己创建一个线程来连接到网络。。

最新更新