繁体   English   中英

Lambda表达式返回空Android

[英]Lambda expression returning null android

我正在编写一个lambda表达式,将给定的经度和纬度转换为地址。 该表达式应该以坐标为参数并返回其对应的地址。 但是,返回的值为null。 以下是我的课程:

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));

lLambdaDeclarations类的对象,以下是相关接口:

public interface CoordinatesToAddressInterface {
String toAddress(double latitude, double longitude, Context context);
}

当我尝试从相关适配器打印坐标时,它们将正确打印。 因此,位置设置正确,但是当我尝试从另一个类访问它时,它显示了字符串的空值。 您能否建议其他方法从表达式中提取位置?

首先, Lambda Expression只是一个匿名类实现,它被设计为用作方法或类参数并解决匿名类的影子问题。
因此,在您的情况下,您根本不需要它,只需像往常一样简单地将CoordinatesToAddressInterface接口实现为命名类即可。

其次,您使用Volley错误,您提供给StringRequest的第一个lambda,此后将是调用响应回调,将在HTTP请求完成但返回语句被调用时调用

return getLocation();

会在setLocation(location)甚至响应回调执行之前立即返回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因为它管理内部状态以帮助您更快地进行请求(缓存),在电话旋转等事件中也可以取消请求,并且销毁请求,在这种情况下,只需调用cancel方法在Activity / Fragment的onStop()

@Override
protected void onStop () {
    super.onStop();
    if (myAdapter.getMyAdapterRequestQueue() != null) {
        myAdapter.getMyAdapterRequestQueue().cancelAll(MyAdapter.TAG);
    }
}

取消请求后,不会调用响应回调。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM