当前位置: 首页 > 知识库问答 >
问题:

创建没有谷歌地图引用的标记(谷歌地图标记)对象

须旭
2023-03-14

我知道周围也有类似的问题,但我无法找到一个可靠的答案,这是我的问题:有没有什么方法可以在没有谷歌地图引用的情况下将标记存储在ArrayList(或任何其他存储)中,然后简单地将它们添加到我的地图中?

背景:我有一个应用程序,目前有大约3500个标记。每个标记还有一个与之相关联的数据(布尔数组存储每个标记的数据,用于根据用户交互使它们可见/不可见)。目前,我使用扩展AsyncTask的类来获取这些标记的位置和数据。加载完成后,我在主线程上使用这些数据创建标记。但是,这需要一些时间,并且在创建标记并将其添加到地图时会冻结UI。我想在后台做这个。

由:com.google.maps.api.android.lib6.common.apiexception.c引起:不在主线程上

我还想过在后台创建MarkerOptions对象,然后用它在主线程中创建标记;但是,我不能向MarkerOption添加标记,它需要添加到标记中。在这种情况下,我需要在主线程中再次遍历所有内容来添加标记,我觉得这并没有为我节省太多的时间/资源。

关于如何创建这些标记并在不阻塞UI的情况下附加它们的标记,任何建议/帮助都将不胜感激?

    private String TAG = LocationLoader.class.getName();
    String[] fileNameArray;

    //ArrayLists
    private ArrayList<BinLocation> mBinLocationArrayList = new ArrayList<>();

    public LocationLoader(Context context, String... fileNames){
        super(context);
        //get the file names that was passed in
        fileNameArray = fileNames;
    }//LocationLoader

    @Override
    protected void onStartLoading() {
        Log.v(TAG, "onStartLoading called");
        forceLoad();
    }//onStartLoading

    @Override
    public ArrayList<BinLocation> loadInBackground() {
        Log.v(TAG, "loadInBackground called");
        String path = "/storage/emulated/0/";
        File file;
        String output = "";

        //Read data from file
        for (int i = 0; i < fileNameArray.length; i++) {
            file = new File(path + fileNameArray[i]);
            try (Scanner scanner = new Scanner(file)) {
                //first line of the text, containing the location and version
                output = scanner.nextLine();
                String prefix = (output.split(":"))[0];
                String line;
                while (scanner.hasNextLine()) {
                    line = scanner.nextLine();
                    String inputArray[] = line.split(",");
                    BinLocation binLocation = new BinLocation(
                            prefix + "-" + inputArray[0],
                            Double.parseDouble(inputArray[1]),
                            Double.parseDouble(inputArray[2]),
                            Integer.parseInt(inputArray[3].trim()),
                            Integer.parseInt(inputArray[4].trim()),
                            Integer.parseInt(inputArray[5].trim()),
                            Integer.parseInt(inputArray[6].trim()));
                    mBinLocationArrayList.add(binLocation);
                }//while
            } catch (Exception e) {
                Log.e(TAG, "File read error: ", e);
            }
        }//for
        Log.v(TAG, "readLocation finished");
        Log.v(TAG, "ArrayList size: " + mBinLocationArrayList.size());
        return mBinLocationArrayList;
    }//loadInBackground
}//LocationLoader class

下面是我的MarkerLoader类(我已经尝试过了,得到了doInBackground()错误)。另外,这里现在没有将数据添加到标记中的代码,但在将数据添加到地图后,它会在循环中进行攻击。

public class MarkerLoader extends AsyncTaskLoader<ArrayList<Marker>> {

    private GoogleMap map;

    private ArrayList<Marker> mMarkerArrayList = new ArrayList<>();

    private ArrayList<MyLocation> mBinLocationArrayList = new ArrayList<>();

    public MarkerLoader (Context context, GoogleMap map, ArrayList<BinLocation> binLocationArrayList) {
        super(context);
        this.map = map;
        this.mBinLocationArrayList = binLocationArrayList;

    }//MarkerLoader

    @Override
    protected void onStartLoading() {
        Log.v(TAG, "onStartLoading called");
        forceLoad();
    }//onStartLoading

    @Override
    public ArrayList<Marker> loadInBackground() {
        Log.v(TAG, "loadInBackground called");
        Marker marker;
        for (BinLocation binLocation : mMyLocationArrayList) {
            marker = map.addMarker(new MarkerOptions()
            .position(binLocation.getPosition()));
            mMarkerArrayList.add(marker);
        }
        Log.v(TAG, "loadInBackground finished, with: " + mMarkerArrayList.size());


        return mMarkerArrayList;
    }
}

这是主活动中的帮助函数(populateMap()),它生成标记并将它们保存在ArrayList中

private void populateMap() {
    if (!checkMapReady() || !mMapIsEmpty) {
        return;
    }//if Map Not ready

//Initialize ArrayList
mMarkerArrayList = new ArrayList<>();

/**
 * This part uses the loop to go through each MyLocation object in the ArrayList, extract
 * all the data, and set the markers
 */

//Check to make sure the BinLocation ArrayList is not empty otherwise we will crash
if (mBinLocationArrayList.isEmpty()) {
    Log.w(TAG, "populateMap() terminated, mBinLocationArrayList empty");
    return;
}//if BinLocation empty

//Safety check to clear the map before populating it
mMap.clear();

//create a markerMyLocation object
Marker mMaker;
//This goes through the ArrayList for every MyLocation object and sets up the markerMyLocation
for (BinLocation binLocation : mBinLocationArrayList) {
    //get boolean values
    boolean[] booleanValues = {binLocation.getGarbage(), binLocation.getContainer(),
            binLocation.getPaper(), binLocation.getCompost()};

    //Set different icon
    switch (markerIconPreference) {
        case "customIcon":
            //custom icon
            //Decide what icon to use
            if (booleanValues[0] && !booleanValues[1] && !booleanValues[2] && !booleanValues[3]) {
                //Make a new MarkerOptions object to add the data
                //garbage markers
                mMaker = mMap.addMarker(new MarkerOptions()
                        .title(binLocation.getId())
                        .position(binLocation.getPosition())
                        .icon(BitmapDescriptorFactory.fromResource(R.drawable.marker_garbage))
                        .visible(garbageVisible));

            } else {
                //Make a new MarkerOptions object to add the data
                //recycling markers
                mMaker = mMap.addMarker(new MarkerOptions()
                        .title(binLocation.getId())
                        .position(binLocation.getPosition())
                        .icon(BitmapDescriptorFactory.fromResource(R.drawable.marker_recycling))
                        .visible(recyclingVisible));
            }
            //Add our boolean array as an object to our markerMyLocation
            mMaker.setTag(booleanValues);
            //Add the markerMyLocation to the ArrayList
            mMarkerArrayList.add(mMaker);
            break;
        case "coloredTeardrop":
            //teardrop icon
            //Decide what icon to use
            if (booleanValues[0] && !booleanValues[1] && !booleanValues[2] && !booleanValues[3]) {
                //Make a new MarkerOptions object to add the data
                //garbage markers
                mMaker = mMap.addMarker(new MarkerOptions()
                        .title(binLocation.getId())
                        .position(binLocation.getPosition())
                        .visible(garbageVisible));
            } else {
                //Make a new MarkerOptions object to add the data
                //recycling markers
                mMaker = mMap.addMarker(new MarkerOptions()
                        .title(binLocation.getId())
                        .position(binLocation.getPosition())
                        .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN))
                        .visible(recyclingVisible));
            }
            //Add our boolean array as an object to our markerMyLocation
            mMaker.setTag(booleanValues);
            //Add the markerMyLocation to the ArrayList
            mMarkerArrayList.add(mMaker);
            break;
    }//switch
}//for
//disable the progress bar
mProgressBar.setVisibility(View.GONE);
//De-activate the CountDown timer since the map is ready
mCountDownTimer.cancel();
//set the boolean to false
mMapIsEmpty = false;

Log.v(TAG, "populateMap finished. Markers: " + mMarkerArrayList.size());
}//populateMap

下面是onMapReady函数

public void onMapReady(GoogleMap map) {
    Log.v(TAG, "onMapReady called");
    mMap = map;

    //Setup on map loaded
    mMap.setOnMapLoadedCallback(this);

    //Check to see if the map is empty and the location array list is not empty and then call populateMap
    if (mMapIsEmpty && !mBinLocationArrayList.isEmpty()) {
        populateMap();
    }//if map empty

//set bounds
mMap.setLatLngBoundsForCameraTarget(GREATER_VANCOUVER_BOUND);
//Set min zoom level to match the bound
mMap.setMinZoomPreference(10.0f);

//disable map toolbar
UiSettings mUiSettings = mMap.getUiSettings();
mUiSettings.setMapToolbarEnabled(false);

//Set listeners
mMap.setOnMarkerClickListener(this);
mMap.setOnInfoWindowCloseListener(this);
mMap.setOnInfoWindowClickListener(this);

// Setting our custom info window, passing out helper method
mMap.setInfoWindowAdapter(new CustomInfoWindowAdapter());

//Here we check for permission and setup the map accordingly
if (!checkLocationPermission()) {
    //Permission is not granted, log, and use the default location
    Log.v(TAG, "No location permission");
    //setup default map
    defaultMapSetup();
} else {
    Log.v(TAG, "Location permission granted");
    //Enable my location and initialize the map there
    mMap.setMyLocationEnabled(true);

    //Setup the map
    locationMapSetup();
}//if -permission
}//onMapReady

共有1个答案

赵俊晤
2023-03-14

尝试在另一个线程中创建标记,如下所示

YourActivity.this.runOnUiThread(new Runnable(){
 public void run(){
//paste your code here.
});
 类似资料:
  • 我已经尝试在这里和谷歌地图API留档上查看了大量的代码块,但仍然无法找出如何隐藏标记。 这是我正在使用的当前代码,它在一个实例中有效。有一次,我在带有标记的函数中添加了“for”循环。setMap(null)Firefox显示以下错误: markers.set地图不是一个函数 附加信息:校园地图和完整代码(不包括地图API)

  • }; 这是在displayRoute()函数之前使用的

  • 我想更改Google Maps上选定的标记图标,因此我有以下代码: 在这一行,我从下面得到错误: 例外情况如下:

  • 我使用的谷歌地图api如下: 这需要拉特和lng,地图画得很好,但是当新的拉特 我想在不重新绘制地图的情况下更新地图上的标记。

  • 所以我正在准备一个页面,其中有一个谷歌地图,有两个形式,即纬度和经度,和一个提交按钮。

  • 我正在为Android制作基于谷歌地图服务的公共交通地图。地图应该包含很多标记(超过300个),它们应该在地图放大和缩小(缩放)时调整大小。现在标记只是互相重叠,有没有办法创建像这样的自定义标记? 我自己也试过,但没有成功。使用android-map-utils库(https://github.com/googlemaps/android-maps-utils)标记现在看起来更好了,但它们不能调整