- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我正在编写一个 GeoFire
插件,我试图让 Dart 代码中的查询监听器可用,但没有成功。我似乎无法弄清楚如何为 EventChannel
设置 StreamHandler
。要了解我的挣扎,您需要看一下我如何创建查询。
这是相关代码:
if (call.method.equals("addGeoQueryEventListener")) {
String refPath = call.argument("refPath");
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
ref = refPath != null ? ref.child(refPath) : ref;
GeoFire geofire = new GeoFire(ref);
List<Double> center = call.argument("center");
double radius = call.argument("radius");
GeoQuery query = geofire.queryAtLocation(new GeoLocation(center.get(0), center.get(1)), radius);
query.addGeoQueryEventListener(new GeoQueryEventListener() {
@Override
public void onKeyEntered(String key, GeoLocation location) {
System.out.println("entered");
}
@Override
public void onKeyExited(String key) {
System.out.println("exited");
}
@Override
public void onKeyMoved(String key, GeoLocation location) {
System.out.println("moved");
}
@Override
public void onGeoQueryReady() {
}
@Override
public void onGeoQueryError(DatabaseError error) {
System.out.println(error.getMessage());
}
});
}
每次调用 addGeoQueryEventListener
时,我都会创建一个全新的 DatabaseReference
,就像在 FlutterFire
插件中所做的那样。我做同样的事情来创建查询。这意味着在此 if 语句
之外没有查询的引用。
所以我创建了一个 EventChannel 来从 onKeyEntered
事件中获取数据。
final EventChannel geoQueryKeyEnteredEventChannel = new EventChannel(registrar.messenger(), "com.bram.vanbilsen.geofire.keyEnteredChannel");
之后,我尝试为该 channel 设置 StreamHandler
:
geoQueryKeyEnteredEventChannel.setStreamHandler(new StreamHandler() {
@Override
public void onListen(Object o, EventSink eventSink) {
}
@Override
public void onCancel(Object o) {
}
});
我如何知道将此 StreamHandler
与我在 addGeoQueryEventListener
中创建的查询监听器连接起来?
---- 编辑 ----
这是我的 registerWith
方法,所有设置都带有一个 MethodChannel
:
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "com.bram.vanbilsen.geofire.GeoFire");
final GeofirePlugin instance = new GeofirePlugin(registrar.activity(), channel);
channel.setMethodCallHandler(instance);
}
这是调用适当方法的更新代码:
if (call.method.equals("addGeoQueryEventListener")) {
String refPath = call.argument("refPath");
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
ref = refPath != null ? ref.child(refPath) : ref;
final GeoFire geofire = new GeoFire(ref);
List<Double> center = call.argument("center");
double radius = call.argument("radius");
GeoQuery query = geofire.queryAtLocation(new GeoLocation(center.get(0), center.get(1)), radius);
query.addGeoQueryEventListener(new GeoQueryEventListener() {
@Override
public void onKeyEntered(String key, GeoLocation location) {
HashMap<String, HashMap<String, ArrayList<Double>>> arguments = new HashMap<>();
HashMap<String, ArrayList<Double>> result = new HashMap<>();
ArrayList<Double> geoLocation = convertGeoLocation(location);
result.put(key, geoLocation);
arguments.put("result", result);
channel.invokeMethod("geoQueryEventKeyEntered", arguments);
}
@Override
public void onKeyExited(String key) {
HashMap<String, String> arguments = new HashMap<>();
arguments.put("result", key);
channel.invokeMethod("geoQueryEventKeyExited", arguments);
}
@Override
public void onKeyMoved(String key, GeoLocation location) {
HashMap<String, HashMap<String, ArrayList<Double>>> arguments = new HashMap<>();
HashMap<String, ArrayList<Double>> result = new HashMap<>();
ArrayList<Double> geoLocation = convertGeoLocation(location);
result.put(key, geoLocation);
arguments.put("result", result);
channel.invokeMethod("geoQueryEventKeyMoved", arguments);
}
@Override
public void onGeoQueryReady() {
HashMap<String, String> arguments = new HashMap<>();
arguments.put("result", "success");
channel.invokeMethod("geoQueryEventReady", arguments);
}
@Override
public void onGeoQueryError(DatabaseError error) {
HashMap<String, HashMap> arguments = new HashMap<>();
HashMap<String, String> databaseError = new HashMap<>();
databaseError.put("code", Integer.toString(error.getCode()));
databaseError.put("details", error.getMessage());
databaseError.put("message", error.getMessage());
arguments.put("result", databaseError);
channel.invokeMethod("geoQueryEventError", arguments);
}
});
} else if ( (call.method.equals("geoQueryEventKeyEntered")) || (call.method.equals("geoQueryEventKeyExited")) ||
(call.method.equals("geoQueryEventKeyMoved")) || (call.method.equals("geoQueryEventReady")) || (call.method.equals("geoQueryEventError")) ) {
result.success(call.argument("result"));
}
我现在如何在我的 Dart 代码中监听函数结果?我是否在孤独的 MethodChannel
上使用了 setMethodCallHandler
?如果是这样,当我必须使用该 channel 来调用与我的监听器无关的方法时,会不会出现问题?
最佳答案
您应该通过 MethodChannel
上的方法调用来完成所有事情,在每个 GeoFire 事件上以 Java 向 Dart 方向发出方法调用,或者使用 EventChannel
来完成所有事情,基本上将 if
语句的代码移动到 StreamHandler
的 listen
方法中。
MethodChannel
:在 Java 方面:
MethodCallChannel myChannel = new MethodCallChannel(messenger, "geofire");
myChannel.setMethodCallHandler(new MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals("addGeoQueryEventListener")) {
// ... setup query using call.arguments
query.addGeoQueryEventListener(new GeoQueryEventListener() {
@Override
public void onKeyEntered(String key, GeoLocation location) {
Map<String, Object> event = // ... extract info from key,location
myChannel.invokeMethod("onKeyEntered", event);
}
@Override
public void onKeyExited(String key) {
myChannel.invokeMethod("onKeyExited", key);
}
// ... other GeoQueryEventListener handlers.
});
result.success(null);
} else {
result.notImplemented();
}
}
});
在 Dart 方面:
const myChannel = const MethodChannel('geofire');
myChannel.setMethodCallHandler((MethodCall call) {
switch (call.method) {
case 'onKeyEntered':
// ... extract event data from call.arguments
return null;
case 'onKeyExited':
// ... extract event data from call.arguments
return null;
// ... other methods
default: throw new MissingPluginException();
}
});
myChannel.invokeMethod('addGeoQueryEventListener', someArguments);
上面的代码使用相同的 channel 进行双向通信。从 Dart 调用 invokeMethod
调用 Java MethodCallHandler
,而从 Java 调用 invokeMethod
调用 Dart 处理程序。
另一种选择是使用两个不同的 channel ,一个用于 Dart->Java 通信以请求设置 GeoFire 监听器,另一个用于 Java->Dart 通信以发送事件。
最佳选择可能取决于您是否对该 channel 有其他用途。我会为不同的目的使用不同的 channel ,因此单个 channel 上的所有通信都以某种方式相关。 channel 非常轻巧;他们只承载着他们名字的重量。
EventChannel
:在 Java 方面:
final EventChannel myChannel = new EventChannel(messenger, "geofire");
myChannel.setStreamHandler(new StreamHandler() {
private GeoQuery query;
private GeoQueryEventListener listener;
@Override
public void onListen(Object arguments, EventSink eventSink) {
query = // ... setup query using arguments
listener = new GeoQueryEventListener() {
@Override
public void onKeyEntered(String key, GeoLocation location) {
Map<String, Object> event = // ... create key entered event
eventSink.success(event);
}
@Override
public void onKeyExited(String key) {
Map<String, Object> event = // ... create key exited event
eventSink.success(event);
}
// ... other GeoQueryEventListener handlers.
}
query.addGeoQueryEventListener(listener);
}
@Override
public void onCancel(Object args) {
query.removeGeoQueryEventListener(listener);
}
});
在 Dart 方面:
const myChannel = const EventChannel('geofire');
myChannel.receiveBroadcastStream(someArguments).listen((event) {
// handle event
});
关于android - 如何将 StreamHandler 与无法访问的对象的监听器连接起来?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46321507/
我是一名优秀的程序员,十分优秀!