Lambda 表达式返回 null android
Lambda expression returning null android
我正在编写一个 lambda 表达式来将给定的纬度和经度转换为地址。该表达式应该将坐标作为参数和 returns 它们的相应地址。但是,返回的值为空。以下是我的class:
public class LambdaDeclarations {
String loc;
private static final String TAG = "LambdaDeclarations";
public CoordinatesToAddressInterface convert = (latitude, longitude, context) -> {
RequestQueue queue = Volley.newRequestQueue(context);
Log.d(TAG, "onCreate: Requesting: Lat: "+latitude+" Lon: "+longitude);
String url ="https://maps.googleapis.com/maps/api/distancematrix/json?units=metric&origins="+latitude+","+longitude+"&destinations="+latitude+","+longitude+"&key=AIzaSyCdKSW0glin4h9sGYa_3hj0L83zI0NsNRo";
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
(String response) -> {
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray destinations = jsonObject.getJSONArray("destination_addresses");
Log.d(TAG, "GETRequest: JSON Object: "+destinations.toString());
String location = destinations.toString();
Log.d(TAG, "Location: "+location);
setLocation(location);
} catch (JSONException e) {
e.printStackTrace();
}
}, error -> Log.d(TAG, "onErrorResponse: That didn't work!"));
queue.add(stringRequest);
return getLocation();
};
public String getLocation() {
return loc;
}
public void setLocation(String location) {
this.loc = location;
}
}
以下是 logcat 的输出:
09-16 10:31:09.160 26525-26525/com.rmit.tejas.mad_foodtruck_2 D/LambdaDeclarations: GETRequest: JSON Object: ["77 State Route 32, West Melbourne VIC 3003, Australia"]
Location: ["77 State Route 32, West Melbourne VIC 3003, Australia"]
09-16 10:31:09.176 26525-26525/com.rmit.tejas.mad_foodtruck_2 D/LambdaDeclarations: GETRequest: JSON Object: ["111 Adderley St, West Melbourne VIC 3003, Australia"]
Location: ["111 Adderley St, West Melbourne VIC 3003, Australia"]
09-16 10:31:09.177 26525-26525/com.rmit.tejas.mad_foodtruck_2 D/LambdaDeclarations: GETRequest: JSON Object: ["4\/326 William St, Melbourne VIC 3000, Australia"]
Location: ["4\/326 William St, Melbourne VIC 3000, Australia"]
以下是我的用法:
myViewHolder.textView3.setText("Location: i->"+i+" add: "+l.convert.toAddress(trackingInfos.get(i).getLatitude(),trackingInfos.get(i).getLongitude(),context));
l
是classLambdaDeclarations
的对象,下面是相关接口:
public interface CoordinatesToAddressInterface {
String toAddress(double latitude, double longitude, Context context);
}
当我尝试从相关适配器打印坐标时,它们打印正确。所以位置设置正确,但是当我尝试从另一个 class 访问它时,它显示字符串的空值。您能否建议一种从表达式中提取位置的替代方法?
首先,Lambda Expression 只是一个匿名 class 实现,它被设计用作方法或 class 参数并解决匿名 [=38] 的阴影问题=].
因此,在您的情况下,您根本不需要它,只需像往常一样简单地实现名为 class 的 CoordinatesToAddressInterface
接口。
其次,你用错了Volley,你提供给StringRequest
的第一个lambda,后面会调用response callback,会在HTTP请求结束时调用,但是return语句
return getLocation();
会在 setLocation(location)
甚至响应回调执行之前立即 return null,这就是为什么每次调用 convert()
时都会得到 null 的原因,尽管您仍然可以看到日志你打印是因为无论如何都会执行响应回调(假设请求成功)。
要正确使用响应回调,您必须更新 UI 内部回调,就像这样
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
public static final String TAG = "MyAdapter";
private RequestQueue mQueue;
public MyAdapter(Context context) {
this.mQueue = Volley.newRequestQueue(context);
}
public RequestQueue getMyAdapterRequestQueue() {
return this.mQueue;
}
...
@Override
public void onBindViewHolder(@NonNull final MyViewHolder holder, int position) {
String url ="some url";
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
(String response) -> {
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray destinations = jsonObject.getJSONArray("destination_addresses");
Log.d(TAG, "GETRequest: JSON Object: "+destinations.toString());
String location = destinations.toString();
Log.d(TAG, "Location: "+location);
// update UI
holder.mTextView.setText(location);
} catch (JSONException e) {
e.printStackTrace();
}
}, error -> Log.d(TAG, "onErrorResponse: That didn't work!"));
stringRequest.setTag(TAG);
mQueue.add(stringRequest);
}
当然,您可以编辑接口的方法签名并让适配器实现该接口(不过我宁愿这样做)但关键是您必须在回调方法中处理异步结果,永远不要期望异步操作的回调在你的下一行代码之前完成。
RequestQueue
不应按请求创建,因为它管理内部状态,可帮助您更快地发出请求(缓存),您也可以在 phone 轮换和你会被销毁,在这种情况下,只需调用 Activity/Fragment 的 onStop()
中的取消方法
@Override
protected void onStop () {
super.onStop();
if (myAdapter.getMyAdapterRequestQueue() != null) {
myAdapter.getMyAdapterRequestQueue().cancelAll(MyAdapter.TAG);
}
}
取消请求后不会调用响应回调。
我正在编写一个 lambda 表达式来将给定的纬度和经度转换为地址。该表达式应该将坐标作为参数和 returns 它们的相应地址。但是,返回的值为空。以下是我的class:
public class LambdaDeclarations {
String loc;
private static final String TAG = "LambdaDeclarations";
public CoordinatesToAddressInterface convert = (latitude, longitude, context) -> {
RequestQueue queue = Volley.newRequestQueue(context);
Log.d(TAG, "onCreate: Requesting: Lat: "+latitude+" Lon: "+longitude);
String url ="https://maps.googleapis.com/maps/api/distancematrix/json?units=metric&origins="+latitude+","+longitude+"&destinations="+latitude+","+longitude+"&key=AIzaSyCdKSW0glin4h9sGYa_3hj0L83zI0NsNRo";
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
(String response) -> {
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray destinations = jsonObject.getJSONArray("destination_addresses");
Log.d(TAG, "GETRequest: JSON Object: "+destinations.toString());
String location = destinations.toString();
Log.d(TAG, "Location: "+location);
setLocation(location);
} catch (JSONException e) {
e.printStackTrace();
}
}, error -> Log.d(TAG, "onErrorResponse: That didn't work!"));
queue.add(stringRequest);
return getLocation();
};
public String getLocation() {
return loc;
}
public void setLocation(String location) {
this.loc = location;
}
}
以下是 logcat 的输出:
09-16 10:31:09.160 26525-26525/com.rmit.tejas.mad_foodtruck_2 D/LambdaDeclarations: GETRequest: JSON Object: ["77 State Route 32, West Melbourne VIC 3003, Australia"]
Location: ["77 State Route 32, West Melbourne VIC 3003, Australia"]
09-16 10:31:09.176 26525-26525/com.rmit.tejas.mad_foodtruck_2 D/LambdaDeclarations: GETRequest: JSON Object: ["111 Adderley St, West Melbourne VIC 3003, Australia"]
Location: ["111 Adderley St, West Melbourne VIC 3003, Australia"]
09-16 10:31:09.177 26525-26525/com.rmit.tejas.mad_foodtruck_2 D/LambdaDeclarations: GETRequest: JSON Object: ["4\/326 William St, Melbourne VIC 3000, Australia"]
Location: ["4\/326 William St, Melbourne VIC 3000, Australia"]
以下是我的用法:
myViewHolder.textView3.setText("Location: i->"+i+" add: "+l.convert.toAddress(trackingInfos.get(i).getLatitude(),trackingInfos.get(i).getLongitude(),context));
l
是classLambdaDeclarations
的对象,下面是相关接口:
public interface CoordinatesToAddressInterface {
String toAddress(double latitude, double longitude, Context context);
}
当我尝试从相关适配器打印坐标时,它们打印正确。所以位置设置正确,但是当我尝试从另一个 class 访问它时,它显示字符串的空值。您能否建议一种从表达式中提取位置的替代方法?
首先,Lambda Expression 只是一个匿名 class 实现,它被设计用作方法或 class 参数并解决匿名 [=38] 的阴影问题=].
因此,在您的情况下,您根本不需要它,只需像往常一样简单地实现名为 class 的 CoordinatesToAddressInterface
接口。
其次,你用错了Volley,你提供给StringRequest
的第一个lambda,后面会调用response callback,会在HTTP请求结束时调用,但是return语句
return getLocation();
会在 setLocation(location)
甚至响应回调执行之前立即 return null,这就是为什么每次调用 convert()
时都会得到 null 的原因,尽管您仍然可以看到日志你打印是因为无论如何都会执行响应回调(假设请求成功)。
要正确使用响应回调,您必须更新 UI 内部回调,就像这样
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
public static final String TAG = "MyAdapter";
private RequestQueue mQueue;
public MyAdapter(Context context) {
this.mQueue = Volley.newRequestQueue(context);
}
public RequestQueue getMyAdapterRequestQueue() {
return this.mQueue;
}
...
@Override
public void onBindViewHolder(@NonNull final MyViewHolder holder, int position) {
String url ="some url";
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
(String response) -> {
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray destinations = jsonObject.getJSONArray("destination_addresses");
Log.d(TAG, "GETRequest: JSON Object: "+destinations.toString());
String location = destinations.toString();
Log.d(TAG, "Location: "+location);
// update UI
holder.mTextView.setText(location);
} catch (JSONException e) {
e.printStackTrace();
}
}, error -> Log.d(TAG, "onErrorResponse: That didn't work!"));
stringRequest.setTag(TAG);
mQueue.add(stringRequest);
}
当然,您可以编辑接口的方法签名并让适配器实现该接口(不过我宁愿这样做)但关键是您必须在回调方法中处理异步结果,永远不要期望异步操作的回调在你的下一行代码之前完成。
RequestQueue
不应按请求创建,因为它管理内部状态,可帮助您更快地发出请求(缓存),您也可以在 phone 轮换和你会被销毁,在这种情况下,只需调用 Activity/Fragment 的 onStop()
@Override
protected void onStop () {
super.onStop();
if (myAdapter.getMyAdapterRequestQueue() != null) {
myAdapter.getMyAdapterRequestQueue().cancelAll(MyAdapter.TAG);
}
}
取消请求后不会调用响应回调。