使用web套接字时Android不在主线程中
我有一个应用程序,我必须使用websockets实时更新谷歌地图上的标记。我成功地完成了与web套接字的连接,并且在响应中得到了json字符串。我解析到JSONObject,当我调试时,我看到json中的所有数据都来了,但问题是当我必须添加标记时。错误是:使用web套接字时Android不在主线程中,android,websocket,google-maps-markers,okhttp,google-maps-api-2,Android,Websocket,Google Maps Markers,Okhttp,Google Maps Api 2,我有一个应用程序,我必须使用websockets实时更新谷歌地图上的标记。我成功地完成了与web套接字的连接,并且在响应中得到了json字符串。我解析到JSONObject,当我调试时,我看到json中的所有数据都来了,但问题是当我必须添加标记时。错误是: e: "com.google.maps.api.android.lib6.common.apiexception.c: Not on the main thread" 连接到websocket后,我执行了以下代码以获取数
e: "com.google.maps.api.android.lib6.common.apiexception.c: Not on the main thread"
连接到websocket后,我执行了以下代码以获取数据:
private OkHttpClient client;
private EchoWebSocketListener webSocketListener;
private static final int NORMAL_CLOSURE_STATUS = 1000;
public void startWebSocketConnection() {
client = new OkHttpClient.Builder()
.readTimeout(3000, TimeUnit.MILLISECONDS)
.build();
webSocketListener = new EchoWebSocketListener(new EchoWebSocketListener.SocketClientListener() {
@Override
public void onConnected(WebSocket webSocket, okhttp3.Response response) {
Log.d("Connected :", response.toString());
}
@Override
public void getMessage(String message) {
Log.d("Received", message);
List<ClusterItem> clusterItems = new ArrayList<>();
try {
JSONObject jsonObject = (JSONObject) new JSONTokener(message).nextValue();
//String vehicle_id = jsonObject.getString("id");
String vehicle_class = jsonObject.getString("vehicle_class");
String kemlercode = jsonObject.getString("kemlercode");
String vehicle_speed = jsonObject.getString("vehicle_speed");
JSONObject newJsonObject = jsonObject.getJSONObject("portalMetadata");
String portal_id = newJsonObject.getString("id");
String portalName = newJsonObject.getString("portalName");
String location = newJsonObject.getString("location");
String[] coordinates = location.split(",");
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
double[] locations = Stream.of(coordinates).mapToDouble(Double::parseDouble).toArray();
double latitude = locations[0];
double longitude = locations[1];
MarkerOptions markerOptions = new MarkerOptions();
LatLng latLng = new LatLng(latitude, longitude);
markerOptions.position(latLng);
Marker marker = mGoogleMap.addMarker(markerOptions);
cameraConfigurations(latLng);
ClusterItem loc = new ClusterItem(latitude, longitude, vehicle_class, kemlercode);
marker.remove();
marker.showInfoWindow();
clusterItems.add(loc);
mClusterManager.addItem(loc);
mGoogleMap.setOnMarkerClickListener(mClusterManager);
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 5.0f));
markers.add(marker);
setClusterManager(mClusterManager, clusterItems);
mGoogleMap.setOnCameraIdleListener(mClusterManager);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(WebSocket webSocket, String reason) {
Log.d("Failure :", reason);
}
@Override
public void closingOrClosed(boolean isClosed, WebSocket webSocket, String reason, int code) {
Log.d("ClosingOrClosed :", isClosed ? "Closed" : "closing");
}
});
Request request = new Request.Builder().url(SOCKET_URL).build();
client.newWebSocket(request, webSocketListener);
}
我正在使用okHttp库执行与WebSocket的通信。
我做错了什么。有人对我需要改进的地方有什么建议吗。任何帮助都将不胜感激。提前感谢。Android不允许在主UI线程中执行网络操作。用工作线程代替。那么,@RemyLebeau你能提供更多的细节吗?你还想让我说什么?由于Android 3,您无法在主UI线程上运行网络代码。时期因此,您需要用辅助线程替换
runOnUiThread()
。我不打算讨论如何编写多线程代码的语义,这对于一个评论来说太宽泛了
runOnUiThread(this::startWebSocketConnection);