如何循环功能并在Android Studio的Google Maps项目的每个循环之间等待一秒钟?

问题描述

我想创建一个程序来标记 google地图上的某个位置,从按下“开始”按钮起,每一秒标记都会向随机方向跳一公里,直到我按下“停止”按钮。

我希望标记跳跃,等待一秒钟,跳跃,等待一秒钟,依此类推...直到我按下“停止”按钮。

当我使用“ while”循环时,程序甚至在显示“ Stop”按钮之前就卡住了。 但是,如果我不使用循环,则效果很好。 能帮我吗?

这是我的代码:

import androidx.annotation.DrawableRes;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;

import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.view.View;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.widget.Button;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.Projection;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptor;
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 java.util.Random;

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

    private GoogleMap mMap;
    private double currLat = 32.671677;
    private double currLng = 35.195678;
    private Marker _marker;
    private boolean _stopBWasNotPressed = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    // Setting the icon instead of the default marker.
    private BitmapDescriptor bitmapDescriptorFromVector(Context context,@DrawableRes int vectorDrawableResourceId) {
        Drawable background = ContextCompat.getDrawable(context,R.drawable.car_icon);
        background.setBounds(0,background.getIntrinsicWidth(),background.getIntrinsicHeight());
        Drawable vectorDrawable = ContextCompat.getDrawable(context,vectorDrawableResourceId);
        vectorDrawable.setBounds(40,20,vectorDrawable.getIntrinsicWidth() + 40,vectorDrawable.getIntrinsicHeight() + 20);
        Bitmap bitmap = Bitmap.createBitmap(background.getIntrinsicWidth(),background.getIntrinsicHeight(),Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        background.draw(canvas);
        vectorDrawable.draw(canvas);
        return BitmapDescriptorFactory.fromBitmap(bitmap);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        // Hide the Stop button.
        Button stopB = (Button) findViewById(R.id.stopB);
        stopB.setVisibility(View.GONE);
        // Hide the Reset button.
        Button resetB = (Button) findViewById(R.id.resetB);
        resetB.setVisibility(View.GONE);
        // Add a marker in my home and move the camera.
        LatLng home = new LatLng(currLat,currLng);
        _marker = mMap.addMarker(new MarkerOptions().position(home).icon(bitmapDescriptorFromVector(this,R.drawable.car_icon)));
        mMap.moveCamera(CameraUpdateFactory.newLatLng(home));

        // Show the Start button.
        Button startB = (Button) findViewById(R.id.startB);
        startB.setVisibility(View.VISIBLE);
        startB.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Hide the Start button.
                Button startB = (Button) findViewById(R.id.startB);
                startB.setVisibility(View.GONE);
                // Show the Stop button.
                final Button stopB = (Button) findViewById(R.id.stopB);
                stopB.setVisibility(View.VISIBLE);

                while (_stopBWasNotPressed) {
                    // Making the program wait a second until it moving the marker again.
                    new Handler().postDelayed(new Runnable() {
                        public void run() {
                            startMoving();
                        }
                    },1000);   // 1 second.
                }
            }
        });
    }

    // This func generates a random number to use as a direction.
    public int generateRandomDirection(){
        final int min = 1;
        final int max = 4;
        final int random = new Random().nextInt((max - min) + 1) + min;
        return random;
    }

    // This func makes the new location and sends it to the animateMarker func.
    public void startMoving(){
        int directionNumber = generateRandomDirection();
        final LatLng toPos;
        switch(directionNumber) {
            case 1:
                toPos = new LatLng((currLat + 0.01),currLng); // North.
                _marker.setPosition(toPos);
                break;
            case 2:
                toPos = new LatLng((currLat - 0.01),currLng); // South.
                _marker.setPosition(toPos);
                break;
            case 3:
                toPos = new LatLng(currLat,(currLng + 0.01)); // East.
                _marker.setPosition(toPos);
                break;
            default:
                toPos = new LatLng(currLat,(currLng - 0.01)); // West.
                _marker.setPosition(toPos);
                break;
        }
    }

    public void stopButtonClick(View view) {
        _stopBWasNotPressed = false; // Stops the while loop.
        // Hide the Stop button.
        Button stopB = (Button) findViewById(R.id.stopB);
        stopB.setVisibility(View.GONE);
        // Show the Reset button.
        final Button resetB = (Button) findViewById(R.id.resetB);
        resetB.setVisibility(View.VISIBLE);
        resetB.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                _marker.setVisible(false);
                currLat = 32.671677;
                currLng = 35.195678;
                onMapReady(mMap);
            }
        });
    }
}

解决方法

我搜索了一下,发现无法同时使用while循环和delay函数,因此将其更改为:

final Handler handler = new Handler();
                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        while (_stopBWasNotPressed) {
                            try {
                                Thread.sleep(1000); // Making the program wait a second until it continues.
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            handler.post(new Runnable() {
                                @Override
                                public void run() {
                                    startMoving();
                                }
                            });
                        }
                    }
                };

                Thread myThread = new Thread(runnable); // Creating a thread for the marker movement.
                myThread.start();

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...