我正在制作一个 map 应用程序,其中显示两点之间的路线(动态)。在这里,我从数据库中检索纬度和经度(可以随时间变化)。这是一个大学项目,所以没有在安全部分工作。这是用于导航的 java 文件:
public class NavigationActivity extends AppCompatActivity implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
GoogleMap.OnMarkerDragListener,
GoogleMap.OnMapLongClickListener,
LocationListener {
private GoogleMap mMap;
GoogleApiClient mGoogleApiClient;
Location mLastLocation;
Marker mCurrLocationMarker;
LocationRequest mLocationRequest;
private double longitude;
private double latitude;
private double fromLongitude;
private double fromLatitude;
private double toLongitude;
private double toLatitude;
private static final String LOGIN_URL = "http://192.168.211.1/xyz/lat.php";
private static final String LOGIN_URLS = "http://192.168.211.1/xyz/lng.php";
public static final String KEY_MYNAME = "User";
public static final String LAT = "lat";
public static final String LANG = "lang";
public LocationManager locationManager;
public Criteria criteria;
public String bestProvider;
private static final String TAG = NavigationActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navigation);
getLocation();
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkLocationPermission();
}
// 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);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
public static boolean isLocationEnabled(Context context)
{
return true;
}
protected void getLocation() {
if (isLocationEnabled(NavigationActivity.this)) {
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
criteria = new Criteria();
bestProvider = String.valueOf(locationManager.getBestProvider(criteria, true)).toString();
//You can still do this if you like, you might get lucky:
Location location = locationManager.getLastKnownLocation(bestProvider);
if (location != null) {
Log.e("TAG", "GPS is on");
latitude = location.getLatitude();
longitude = location.getLongitude();
// Toast.makeText(NavigationActivity.this, "latitude:" + latitude + " longitude:" + longitude, Toast.LENGTH_SHORT).show();
//Trying to send the data to the database
final StringRequest stringrequest=new StringRequest(Request.Method.POST,LOGIN_URL,new Response.Listener<String>(){
@Override
public void onResponse(String s) {
if (!s.equalsIgnoreCase("updated")) {
Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show();
getPoints();
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
Toast.makeText(getApplicationContext(), volleyError.toString(), Toast.LENGTH_LONG).show();
}
}){
protected Map<String,String> getParams(){
Map<String,String>params=new HashMap<String, String>();
SharedPreferences sharedPreferences = NavigationActivity.this.getSharedPreferences(Config.SHARED_PREF_NAME, Context.MODE_PRIVATE);
String KEY_MYUSERNAME = sharedPreferences.getString(Config.EMAIL_SHARED_PREF, "Not Found");
params.put(LAT, String.valueOf(latitude));
params.put(LANG, String.valueOf(longitude));
params.put(KEY_MYNAME, KEY_MYUSERNAME);
return params;
}
};
RequestQueue requestQueue= Volley.newRequestQueue(this);
requestQueue.add(stringrequest);
} else {
//This is what you need:
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
locationManager.requestLocationUpdates(bestProvider, 1000, 0, this);
}
}
else
{
//prompt user to enable location....
//.................
}
}
@Override
protected void onStart() {
mGoogleApiClient.connect();
super.onStart();
}
@Override
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
//Initialize Google Play Services
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
} else {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
@Override
public void onConnected(Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
// if (ContextCompat.checkSelfPermission(this,
// Manifest.permission.ACCESS_FINE_LOCATION)
// == PackageManager.PERMISSION_GRANTED) {
// LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
// }
}
private void getPoints() {
//Getting the URL
fromLatitude = latitude;
fromLongitude = longitude;
//To get to latitude
StringRequest stringRequests = new StringRequest(Request.Method.POST, LOGIN_URL,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
if (response.equalsIgnoreCase("Connection Error")) {
Toast.makeText(NavigationActivity.this, response, Toast.LENGTH_SHORT).show();
}
else {
toLatitude = Double.parseDouble(response);
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(NavigationActivity.this, error.toString(), Toast.LENGTH_LONG).show();
}
}) {
@Override
protected Map<String, String> getParams() {
SharedPreferences sharedPreferences = NavigationActivity.this.getSharedPreferences(Config.SHARED_PREF_NAME, Context.MODE_PRIVATE);
String KEY_MYUSERNAME = sharedPreferences.getString(Config.EMAIL_SHARED_PREF,"Not Found");
Map<String,String> params = new HashMap<String, String>();
params.put(KEY_MYNAME,KEY_MYUSERNAME);
return params;
}
};
RequestQueue requestQueues = Volley.newRequestQueue(this);
requestQueues.add(stringRequests);
StringRequest stringRequestss = new StringRequest(Request.Method.POST, LOGIN_URLS,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
if (response.equalsIgnoreCase("Connection Error")) {
Toast.makeText(NavigationActivity.this, response, Toast.LENGTH_SHORT).show();
}
else {
toLongitude = Double.parseDouble(response);
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(NavigationActivity.this, error.toString(), Toast.LENGTH_LONG).show();
}
}) {
@Override
protected Map<String, String> getParams() {
SharedPreferences sharedPreferences = NavigationActivity.this.getSharedPreferences(Config.SHARED_PREF_NAME, Context.MODE_PRIVATE);
String KEY_MYUSERNAME = sharedPreferences.getString(Config.EMAIL_SHARED_PREF,"Not Found");
Map<String,String> params = new HashMap<String, String>();
params.put(KEY_MYNAME,KEY_MYUSERNAME);
return params;
}
};
RequestQueue requestQueuess = Volley.newRequestQueue(this);
requestQueuess.add(stringRequestss);
getDirections();
}
private void getDirections() {
double flat = fromLatitude;
double flong = fromLongitude;
double tlat = toLatitude;
double tlong = toLongitude;
LatLng origin = new LatLng(flat, flong);
LatLng dest = new LatLng(tlat, tlong);
String url = getDirectionsUrl(origin, dest);
DownloadTask downloadTask = new DownloadTask();
// Start downloading json data from Google Directions API
downloadTask.execute(url);
}
private String getDirectionsUrl(LatLng origin,LatLng dest){
// Origin of route
String str_origin = "origin="+origin.latitude+","+origin.longitude;
// Destination of route
String str_dest = "destination="+dest.latitude+","+dest.longitude;
// Sensor enabled
String sensor = "sensor=false";
// Building the parameters to the web service
String parameters = str_origin+"&"+str_dest+"&"+sensor;
// Output format
String output = "json";
// Building the url to the web service
String url = "https://maps.googleapis.com/maps/api/directions/"+output+"?"+parameters;
return url;
}
private String downloadUrl(String strUrl) throws IOException{
String data = "";
InputStream iStream = null;
HttpURLConnection urlConnection = null;
try{
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while( ( line = br.readLine()) != null){
sb.append(line);
}
data = sb.toString();
br.close();
}catch(Exception e){
}finally{
iStream.close();
urlConnection.disconnect();
}
return data;
}
// Fetches data from url passed
private class DownloadTask extends AsyncTask<String, Void, String> {
// Downloading data in non-ui thread
@Override
protected String doInBackground(String... url) {
// For storing data from web service
String data = "";
try{
// Fetching the data from web service
data = downloadUrl(url[0]);
}catch(Exception e){
Log.d("Background Task",e.toString());
}
return data;
}
// Executes in UI thread, after the execution of
// doInBackground()
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
ParserTask parserTask = new ParserTask();
// Invokes the thread for parsing the JSON data
parserTask.execute(result);
}
}
/** A class to parse the Google Places in JSON format */
private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String,String>>> >{
// Parsing the data in non-ui thread
@Override
protected List<List<HashMap<String, String>>> doInBackground(String... jsonData) {
JSONObject jObject;
List<List<HashMap<String, String>>> routes = null;
try{
jObject = new JSONObject(jsonData[0]);
DirectionsJSONParser parser = new DirectionsJSONParser();
// Starts parsing data
routes = parser.parse(jObject);
}catch(Exception e){
e.printStackTrace();
}
return routes;
}
// Executes in UI thread, after the parsing process
@Override
protected void onPostExecute(List<List<HashMap<String, String>>> result) {
ArrayList<LatLng> points = null;
PolylineOptions lineOptions = null;
MarkerOptions markerOptions = new MarkerOptions();
// Traversing through all the routes
for(int i=0;i<result.size();i++){
points = new ArrayList<LatLng>();
lineOptions = new PolylineOptions();
// Fetching i-th route
List<HashMap<String, String>> path = result.get(i);
// Fetching all the points in i-th route
for(int j=0;j<path.size();j++){
HashMap<String,String> point = path.get(j);
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
LatLng position = new LatLng(lat, lng);
points.add(position);
}
// Adding all the points in the route to LineOptions
lineOptions.addAll(points);
lineOptions.width(2);
lineOptions.color(Color.RED);
}
// Drawing polyline in the Google Map for the i-th route
mMap.addPolyline(lineOptions);
}
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onLocationChanged(final Location location) {
getLocation();
mLastLocation = location;
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
//Place current location marker
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("Current Position");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
mCurrLocationMarker = mMap.addMarker(markerOptions);
Toast.makeText(NavigationActivity.this, String.valueOf(location.getLatitude()), Toast.LENGTH_LONG).show();
//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
//stop location updates
if (mGoogleApiClient != null) { LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, (com.google.android.gms.location.LocationListener) this);
}
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Toast.makeText(NavigationActivity.this, "Connection Lost", Toast.LENGTH_LONG).show();
}
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
public boolean checkLocationPermission() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Asking user if explanation is needed
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
return false;
} else {
return true;
}
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted. Do the
// contacts-related task you need to do.
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
if (mGoogleApiClient == null) {
buildGoogleApiClient();
}
mMap.setMyLocationEnabled(true);
}
} else {
// Permission denied, Disable the functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
}
return;
}
}
}
}
这是我的日志:
03-24 15:00:51.174 9970-9970/com.xyz.user.xyz E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.xyz.user.xyz, PID: 9970
java.lang.NullPointerException: PolylineOptions cannot be null.
at com.google.maps.api.android.lib6.common.k.a(:com.google.android.gms.DynamiteModulesB:42)
at com.google.maps.api.android.lib6.impl.dp.<init>(:com.google.android.gms.DynamiteModulesB:146)
at com.google.maps.api.android.lib6.impl.az.a(:com.google.android.gms.DynamiteModulesB:931)
at com.google.android.gms.maps.internal.l.onTransact(:com.google.android.gms.DynamiteModulesB:137)
at android.os.Binder.transact(Binder.java:380)
at com.google.android.gms.maps.internal.IGoogleMapDelegate$zza$zza.addPolyline(Unknown Source)
at com.google.android.gms.maps.GoogleMap.addPolyline(Unknown Source)
at com.xyz.user.xyz.NavigationActivity$ParserTask.onPostExecute(NavigationActivity.java:474)
at com.xyz.user.xyz.NavigationActivity$ParserTask.onPostExecute(NavigationActivity.java:420)
at android.os.AsyncTask.finish(AsyncTask.java:636)
at android.os.AsyncTask.access$500(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:653)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5343)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
谁能给我一些解决方案?
我尝试使用下面的代码:
if(lineOptions!=null)
{
mMap.addPolyline(lineOptions);
}
上面的代码有助于避免应用程序崩溃,但它仍然无法帮助我绘制这些点之间的路线。
检索到的数据是正确的,我用toast检查过。
最佳答案
我检查了你的代码,发现了一些导致崩溃的问题,首先你初始化了 null ArrayList<LatLng>points=null和 PolylineOptions lineOptions=null那么如果路径为 null 那么 lineOptions 怎么办?太空了,因此我修复了代码下面的行审查应用它运行它,如果成功享受!
@Override
protected void onPostExecute(List<List<HashMap<String, String>>> result) {
ArrayList<LatLng> points = new ArrayList<LatLng>();;
PolylineOptions lineOptions = new PolylineOptions();;
lineOptions.width(2);
lineOptions.color(Color.RED);
MarkerOptions markerOptions = new MarkerOptions();
// Traversing through all the routes
for(int i=0;i<result.size();i++){
// Fetching i-th route
List<HashMap<String, String>> path = result.get(i);
// Fetching all the points in i-th route
for(int j=0;j<path.size();j++){
HashMap<String,String> point = path.get(j);
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
LatLng position = new LatLng(lat, lng);
points.add(position);
}
// Adding all the points in the route to LineOptions
lineOptions.addAll(points);
}
// Drawing polyline in the Google Map for the i-th route
if(points.size()!=0)mMap.addPolyline(lineOptions);//to avoid crash
}
关于android - 折线选项不能为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42996662/
我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val
这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb
我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co
最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路
print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上
我正在使用Rails3.2.3和Ruby1.9.3p0。我发现我经常需要确定某个字符串是否出现在选项列表中。看来我可以使用Ruby数组.includemethod:或正则表达式equals-tildematchshorthand用竖线分隔选项:就性能而言,一个比另一个好吗?还有更好的方法吗? 最佳答案 总结:Array#include?包含String元素,在接受和拒绝输入时均胜出,对于您的示例只有三个可接受的值。对于要检查的更大的集合,看起来Set#include?和String元素可能会获胜。如何测试我们应该根据经验对此进行测试
我对此有点困惑。我在RoR项目中的最终目标是从我的数据库中获取单个随机配置文件。我想它应该是这样的:@profile=Profile.find_by_user_id(rand(User.count))它一直抛出错误,因为user_id0不存在,所以我把它的一部分拿出来检查发生了什么:@r=rand(User.count)每次都返回0。发生什么了?我注册了5个假用户和5个相关配置文件来测试这个。如果我将Profile.find_by_user_id(rand(User.count))重写为Profile.find_by_user_id(3)它工作得很好。User.count也在工作。所以
这个问题困扰了我一段时间。这不是一件困难的事情,但我不知道为什么没有简单的方法来做到这一点,我敢打赌有但我没有看到。我只想取一个散列,像这样:cars={:bob=>'Pontiac',:fred=>'Chrysler',:lisa=>'Cadillac',:mary=>'Jaguar'}然后做类似的事情cars[:bob,:lisa]得到{:bob=>'Pontiac',:lisa=>'Cadillac'}我这样做了,效果很好:classHashdefpick(*keys)Hash[select{|k,v|keys.include?(k)}]endendruby-1.8.7-p249
在纯Rubyirb中,不能输入{if:1}。该语句不会终止,因为irb认为if不是符号,而是if语句的开始。那么为什么Rails可以有before_filter接受if作为参数?该指南的代码如下:classOrderunless也会发生同样的事情。 最佳答案 这是一个irb问题,而不是Ruby。bash=>ruby-e"puts({if:1})"bash=#{:if=>1}您可以改用pry。它将正确读取输入。https://github.com/pry/pry 关于ruby-on-rai
Enumerable#each和Enumerable#map的区别在于返回的是接收者还是映射后的结果。回到接收者是微不足道的,你通常不需要在each之后继续一个方法链,比如each{...}.another_method(我可能没见过这样的案例。即使你想回到接收者那里,你也可以通过tap来实现)。所以我认为所有或者大部分使用Enumerable#each的情况都可以用Enumerable#map代替。我错了吗?如果我是对的,each的目的是什么?map是否比each慢?编辑:我知道当您对返回值不感兴趣时使用each是一种常见的做法。我对这种做法是否存在不感兴趣,但感兴趣的是,除了从