我在我的应用程序中使用Google place API来搜索位置。当用户在编辑字段中输入文本时,调用的API和结果输出将显示在列表中。
我成功实现了它,但问题是每次编辑字段文本更改时,列表都不会重新绘制,输出会添加到列表的 end 。我希望每次文本在编辑文本字段中更改时,列表必须删除以前无效的内容。
这可以在图片中看到:
为了实现这个,我写了这段代码:
public final class MyScreen extends MainScreen {
/**
* Creates a new MyScreen object
*/
private Vector _listElements;
ListField list;
JSONObject[] jsonobject;
EditField editfield;
String url = "https://maps.googleapis.com/maps/api/place/autocomplete/json?input=";
String[] locationName;
VerticalFieldManager verticalFieldManager = new VerticalFieldManager();
public MyScreen() {
ButtonField search = new ButtonField("Search");
_listElements = new Vector();
list = new ListField();
ListCallback _callback = new ListCallback(this);
// Set the displayed title of the screen
setTitle("Search Edit Field");
editfield = new EditField();
editfield.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
list.invalidate();
createField();
}
});
}
});
list.setCallback(_callback);
add(editfield);
add(new SeparatorField());
verticalFieldManager.add(list);
add(verticalFieldManager);
}
protected void createField() {
ShowList();
reloadList();
}
private void reloadList() {
list.setSize(_listElements.size());
}
class ListCallback implements ListFieldCallback {
MyScreen listDemoScreen;
public ListCallback(MyScreen listDemoScreen) {
this.listDemoScreen = listDemoScreen;
}
public void drawListRow(ListField list, Graphics g, int index, int y,
int w) {
String text = (String) _listElements.elementAt(index);
list.setRowHeight(getFont().getHeight());
g.drawText(text, 0, y, 0, -1);
}
public Object get(ListField list, int index) {
return _listElements.elementAt(index);
}
public int indexOfList(ListField list, String prefix, int string) {
return _listElements.indexOf(prefix, string);
}
public int getPreferredWidth(ListField list) {
return Display.getWidth();
}
}
protected void ShowList() {
HttpConnection httpConn;
InputStream in;
ConnectionFactory connFact = new ConnectionFactory();
ConnectionDescriptor connDesc;
String response;
String fieldText = editfield.getText();
connDesc = connFact.getConnection(url + fieldText
+ "%@&sensor=true&key=xxxxxxxxxxxxx"
+ ConnectionType.getConnectionType());
if (connDesc != null) {
httpConn = (HttpConnection) connDesc.getConnection();
try {
int responseCode = httpConn.getResponseCode();
if (responseCode == HttpConnection.HTTP_OK) {
in = httpConn.openInputStream();
StringBuffer buf = new StringBuffer();
int read = -1;
while ((read = in.read()) != -1)
buf.append((char) read);
response = buf.toString();
try {
JSONObject object = new JSONObject(response);
JSONArray ar = object.getJSONArray("predictions");
jsonobject = new JSONObject[ar.length()];
locationName = new String[ar.length()];
list.invalidate();
for (int i = 0; i < ar.length(); i++) {
jsonobject[i] = ar.getJSONObject(i);
_listElements.addElement(jsonobject[i]
.getString("description"));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
} else {
Dialog.alert("Connection not succeded");
}
}
protected boolean onSavePrompt() {
return true;
}
}
更新和解决方案:
只修改这个,这个休息工作正常。正如Peter建议的那样,我们还可以设置Thread.sleep(time);
以便不阻止UI:
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
_listElements.removeAllElements();
createField();
}
});
答案 0 :(得分:1)
我认为您的问题只是在请求更多数据时不清除_listElements向量。所以_listElements只会变大。
然而,这里存在一个更大的问题,那就是您的代码似乎在事件线程上运行网络操作。你应该在你的changeListener中做什么。启动一个请求数据的线程,然后在此步骤获取数据时重新填充ListField。
由于此更改,UI不会被阻止,并且列表更新将变为异步,因此您的用户实际上可以在第一个Thread响应返回之前在EditField中输入另一个字符。为了防止这看起来很愚蠢,你可以延迟线程处理几秒钟以查看是否输入了另一个字符,和/或你可以确保在重新填充之前EditField内容仍然与请求的字符相同。
我个人更喜欢这种异步方法,但如果它困扰你,你可以设置一个'请等待 - 加载'类型的屏幕来阻止用户,直到响应回来。
<强>更新强>
请记住,如果您启动后台线程,则需要返回事件线程来执行Ui处理。通常,只需将UI代码包含在稍后调用的Runnable的run方法中即可完成此操作,例如:
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
// Ui Code in here
}
});
您应该只在运行中放置Ui更新代码。不应包括网络处理或任何其他阻止操作。