折线在模拟器上崩溃

时间:2019-11-29 13:40:18

标签: java android nullpointerexception

我正在尝试在地图上绘制一条折线

导入com.google.android.gms.maps.model.Polyline; 导入com.google.android.gms.maps.model.PolylineOptions;

import java.util.ArrayList; 导入java.util.List;

公共类MainActivity扩展了AppCompatActivity,它实现了OnMapReadyCallback,SeekBar.OnSeekBarChangeListener {     //初始化变量

GoogleMap gMap;
SeekBar seekWidth, seekBlue, seekGreen, seekRed;
Button btClear, btDraw;

Polyline polyline = null;
List<LatLng> latLngList = new ArrayList<>();
List<Marker> markerList = new ArrayList<>();

PolylineOptions polylineOptions = null;

int red = 0, green= 0, blue=0;

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


    //Assign variable
    seekWidth = findViewById(R.id.seek_width);
    seekRed = findViewById(R.id.seek_red);
    seekGreen = findViewById(R.id.seek_green);
    seekBlue = findViewById(R.id.seek_blue);
    btDraw=findViewById(R.id.bt_draw);
    btClear=findViewById(R.id.bt_clear);

    /*Initialise SupportMapFragment
    SupportMapFragment supportMapFragment = (SupportMapFragment)getSupportFragmentManager()
            .findFragmentById(R.id.google_map);
    supportMapFragment.getMapAsync(this);

    btDraw.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //Draw Polyline on Map
            if (polyline!=null) polyline.remove();
            //Create PolylineOptions
            PolylineOptions polylineOptions = new PolylineOptions()
                    .addAll(latLngList).clickable(true);
            polyline = gMap.addPolyline(polylineOptions);

            setWidth();

        }
    });*/

    //Initialise SupportMapFragment
    SupportMapFragment supportMapFragment = (SupportMapFragment)getSupportFragmentManager()
            .findFragmentById(R.id.google_map);
    supportMapFragment.getMapAsync(this);

    btDraw.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //Draw Polyline on Map
            if (polyline!=null) polyline.remove();
            if(polylineOptions!=null){
                //Create PolylineOptions
                polyline = gMap.addPolyline(polylineOptions);

                setWidth();
            }
        }
    });

    btClear.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //Clear All
            if (polyline!=null) polyline.remove();
            for(Marker marker: markerList) marker.remove();
            latLngList.clear();
            markerList.clear();
            seekWidth.setProgress(3);
            seekBlue.setProgress(0);
            seekGreen.setProgress(0);
            seekRed.setProgress(0);

        }
    });

    seekRed.setOnSeekBarChangeListener(this);
    seekGreen.setOnSeekBarChangeListener(this);
    seekBlue.setOnSeekBarChangeListener(this);


}

private void setWidth() {
    seekWidth.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            //Get Seekbar Progress
            int width = seekWidth.getProgress();
            if (polyline != null) {
                //Set Polyline Width
                polyline.setWidth(width);
            }
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

        }
    });
}

/*@Override
public void onMapReady(GoogleMap googleMap) {
    /*gMap= googleMap;
    gMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
        @Override
        public void onMapClick(LatLng latLng) {
            //Create MarkerOptions
            MarkerOptions markerOptions = new MarkerOptions().position(latLng);
            //Create Marker
            Marker marker = gMap.addMarker(markerOptions);
            //Add Latlng and Marker
            latLngList.add(latLng);
            markerList.add(marker);
        }
    });

}*/

    public void onMapReady(GoogleMap googleMap) {
        gMap= googleMap;
        gMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
            @Override
            public void onMapClick(LatLng latLng) {
                //Create MarkerOptions
                MarkerOptions markerOptions = new MarkerOptions().position(latLng);
                //Create Marker
                Marker marker = gMap.addMarker(markerOptions);
                //Add Latlng and Marker
                latLngList.add(latLng);
                markerList.add(marker);

                polylineOptions = new PolylineOptions().addAll(latLngList).clickable(true);
            }
        });
    }

@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
    switch (seekBar.getId()){
        case R.id.seek_red:
            red = i;
            break;
        case R.id.seek_green:
            green = i;
            break;
        case R.id.seek_blue:
            blue= i;
            break;

    }
    if(polyline !=null){
    //Set Polyline Color
        polyline.setColor(Color.rgb(red,green,blue));
    }


}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {

}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {

}

}

错误如下:

  

2019-11-29 13:39:40.391 20694-20694 / com.example.poly E / AndroidRuntime:   致命异常:主要       流程:com.example.poly,PID:20694        java.lang.NullPointerException:尝试在计算机上调用虚拟方法'void com.google.android.gms.maps.model.Polyline.setColor(int)'   空对象引用           在com.example.poly.MainActivity.onProgressChanged(MainActivity.java:149)           在android.widget.SeekBar.onProgressRefresh(SeekBar.java:93)           在android.widget.ProgressBar.doRefreshProgress(ProgressBar.java:1327)           在android.widget.ProgressBar.refreshProgress(ProgressBar.java:1382)           在android.widget.ProgressBar.setProgressInternal(ProgressBar.java:1447)           在android.widget.AbsSeekBar.trackTouchEvent(AbsSeekBar.java:850)           在android.widget.AbsSeekBar.onTouchEvent(AbsSeekBar.java:760)           在android.view.View.dispatchTouchEvent(View.java:9943)           在android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)           在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358)           在android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)           在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358)           在android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)           在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358)           在android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)           在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358)           在android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)           在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358)           在android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)           在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358)           在android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669)           在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358)           在com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:411)           在com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1810)           在android.app.Activity.dispatchTouchEvent(Activity.java:3061)           在androidx.appcompat.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69)           在com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:373)           在android.view.View.dispatchPointerEvent(View.java:10163)           在android.view.ViewRootImpl $ ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4434)           在android.view.ViewRootImpl $ ViewPostImeInputStage.onProcess(ViewRootImpl.java:4302)           在android.view.ViewRootImpl $ InputStage.deliver(ViewRootImpl.java:3849)           在android.view.ViewRootImpl $ InputStage.onDeliverToNext(ViewRootImpl.java:3902)           在android.view.ViewRootImpl $ InputStage.forward(ViewRootImpl.java:3868)           在android.view.ViewRootImpl $ AsyncInputStage.forward(ViewRootImpl.java:3995)           在android.view.ViewRootImpl $ InputStage.apply(ViewRootImpl.java:3876)           在android.view.ViewRootImpl $ AsyncInputStage.apply(ViewRootImpl.java:4052)           在android.view.ViewRootImpl $ InputStage.deliver(ViewRootImpl.java:3849)           在android.view.ViewRootImpl $ InputStage.onDeliverToNext(ViewRootImpl.java:3902)           在android.view.ViewRootImpl $ InputStage.forward(ViewRootImpl.java:3868)           在android.view.ViewRootImpl $ InputStage.apply(ViewRootImpl.java:3876)           在android.view.ViewRootImpl $ InputStage.deliver(ViewRootImpl.java:3849)           在android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6210)           在android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6184)           在android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6145)           在android.view.ViewRootImpl $ WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6313)           在android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)           在android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native   方法)           在android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:176)           在android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:6284)           在android.view.ViewRootImpl $ ConsumeBatchedInputRunnable.run(ViewRootImpl.java:6336)

1 个答案:

答案 0 :(得分:1)

  

实际上,这可能是临时修复或永久修复,具体取决于折线为何仍为null的根本原因,但是下面应该解决您的崩溃问题。

     

注意:我用注释来解释下面代码的各个方面。

  

第一件事是更改以下代码段:

if(polyline!=null) /*Note that without the curly brace, the if statement will only be applied to the immediate code below, so in your case, polyline is still also null here as the if statement only applies to the comment which will be ignored by the compiler. */ 
  //Set Polyline Width
  polyline.setWidth(width);
  

到下面:

if(polyline!=null){ /*you should try and always use your opening and closing brace for readability. */
    //Set Polyline Width
    polyline.setWidth(width);
}
  

第二个是导致崩溃的主要原因:

//Set Polyline Color
polyline.setColor(Color.rgb(red,green,blue)); /* you for got to place a check here which is why you get the crash because as at here, *polyline* is still null for some reasons. */
  

因此,将上面的摘录立即更改为以下内容:

if(polyline !=null){
//Set Polyline Color
polyline.setColor(Color.rgb(red,green,blue));
}
  

此外,@ cricket_007指出:

就像您上面有 Polyline polyline = null; 一样,还添加以下内容:PolylineOptions polylineOptions = null;

  

,如下所示修改您的 SupportMapFragment

    //Initialise SupportMapFragment
            SupportMapFragment supportMapFragment = (SupportMapFragment)getSupportFragmentManager()
                    .findFragmentById(R.id.google_map);
            supportMapFragment.getMapAsync(this);

            btDraw.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    //Draw Polyline on Map
                    if (polyline!=null) polyline.remove();
                       if(polylineOptions!=null){
                          //Create PolylineOptions
                    polyline = gMap.addPolyline(polylineOptions);

                    setWidth();
                   }   
                }
            });
  

然后在这里:

    @Override
    public void onMapReady(GoogleMap googleMap) {
        gMap= googleMap;
        gMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
            @Override
            public void onMapClick(LatLng latLng) {
                //Create MarkerOptions
                MarkerOptions markerOptions = new MarkerOptions().position(latLng);
                //Create Marker
                Marker marker = gMap.addMarker(markerOptions);
                //Add Latlng and Marker
                latLngList.add(latLng);
                markerList.add(marker);

                polylineOptions = new PolylineOptions().addAll(latLngList).clickable(true);
            }
        });
    }
  

由于您是Android的新手,如果发现很难找到上面的代码在代码中的位置,请简单复制例如 polyline.setColor(Color.rgb(red,green,blue)); 并导航至您的AndroidStudio并导航找到,然后将其粘贴到此处,以帮助您找到代码的确切位置。   祝您好运。

...

  

新答案:

     

下面是完整的Java类,包括所有需要的导入,只需复制和替换即可,因为它具有相同的程序包名称,其他所有内容都相同。

package com.example.poly;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
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 com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback, SeekBar.OnSeekBarChangeListener {
    //Initialise variables
    GoogleMap gMap;
    SeekBar seekWidth, seekBlue, seekGreen, seekRed;
    Button btClear, btDraw;

    List<LatLng> latLngList = new ArrayList<>();
    List<Marker> markerList = new ArrayList<>();
    int red = 0, green= 0, blue=0;

    Polyline polyline = null;
    PolylineOptions polylineOptions = null;

    private static int PERMISSION_LOCATION_STATE = 1001; //hopefully no other permission code conflict with this in the future, so watch out.

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

        //Assign variable
        seekWidth = findViewById(R.id.seek_width);
        seekRed = findViewById(R.id.seek_red);
        seekGreen = findViewById(R.id.seek_green);
        seekBlue = findViewById(R.id.seek_blue);
        btDraw=findViewById(R.id.bt_draw);
        btClear=findViewById(R.id.bt_clear);

        /* We decide to put our function inside a runner that runs on UI thread to at least try to
         * load the page before prompting users to allow location access, this will delay the prompt by 2 seconds.
         * Note: it's actually not compulsory, so you can remove it either way, it will work.
         * */
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                mapPermissionCheck();
            }
        }, 2000);

        btDraw.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //Draw Polyline on Map
                if (polyline!=null) polyline.remove();
                if(polylineOptions!=null){
                    //Create PolylineOptions
                    polyline = gMap.addPolyline(polylineOptions);
                    setWidth();
                }
            }
        });

        btClear.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Clear All
                if (polyline!=null) polyline.remove();
                for(Marker marker: markerList) marker.remove();
                latLngList.clear();
                markerList.clear();
                seekWidth.setProgress(3);
                seekBlue.setProgress(0);
                seekGreen.setProgress(0);
                seekRed.setProgress(0);
            }
        });

        seekRed.setOnSeekBarChangeListener(this);
        seekGreen.setOnSeekBarChangeListener(this);
        seekBlue.setOnSeekBarChangeListener(this);
    }

    private void initSupportFragment() {
        SupportMapFragment supportMapFragment = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.google_map);
        if(supportMapFragment!=null){
            supportMapFragment.getMapAsync(this);
        }
    }

    private void mapPermissionCheck() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
                == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            //Initialise SupportMapFragment when we're sure permission is granted to access location, else Map will not be ready and mapReady() will never be called.
            initSupportFragment();
        }else{
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_LOCATION_STATE);
        }
    }

    private void setWidth() {
        seekWidth.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                //Get Seekbar Progress
                int width = seekWidth.getProgress();
                if (polyline != null) {
                    //Set Polyline Width
                    polyline.setWidth(width);
                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
            gMap= googleMap;
            gMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
                @Override
                public void onMapClick(LatLng latLng) {
                    //Create MarkerOptions
                    MarkerOptions markerOptions = new MarkerOptions().position(latLng);
                    //Create Marker
                    Marker marker = gMap.addMarker(markerOptions);
                    //Add Latlng and Marker
                    latLngList.add(latLng);
                    markerList.add(marker);

                    polylineOptions = new PolylineOptions().addAll(latLngList).clickable(true);
                }
            });
        }

    @Override
    public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
        switch (seekBar.getId()){
            case R.id.seek_red:
                red = i;
                break;
            case R.id.seek_green:
                green = i;
                break;
            case R.id.seek_blue:
                blue= i;
                break;
        }

        if(polyline !=null){
        //Set Polyline Color
            polyline.setColor(Color.rgb(red,green,blue));
        }
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {

    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {

    }

    /*
    * Right below here is a permission callback method that get called when ever an action is taken on a permission prompt request
    * So, if a user declined or accept, we can check and decide what to do next, in this case, we will try enforce the user to
    * give us location access in case they declined at first since we can't do much without the permission.
    * */
    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == PERMISSION_LOCATION_STATE) { // remember PERMISSION_LOCATION_STATE? check above on how we parse it.
                if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
                    new AlertDialog.Builder(this)
                        .setTitle("Location Permission Needed")
                        .setMessage("Daniel Poly App Need Your Location Permission To Proceed.")
                        .setCancelable(false)
                        .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.cancel();
                                mapPermissionCheck();
                            }
                        })
                        .show();
                }else{ //Meaning permission finally granted....hurray!!!
                    initSupportFragment();
                }
        }
    }

}
  

最后,您错过的是权限。   您应该read以获取更多信息。