1

我在我的应用程序中使用 Google place API 来搜索位置。当用户在编辑字段中输入文本时,调用的 API 和结果输出将显示在列表中。

我成功实现了它,但问题是每次编辑字段文本更改时,列表都不会重新绘制,并且输出会添加到列表的末尾。我希望每次编辑文本字段中的文本更改时,列表都必须删除其先前无效的内容。

这可以在图片中看到:

在此处输入图像描述 在此处输入图像描述 在此处输入图像描述

为了实现这一点,我编写了以下代码:

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

更新和解决方案:

只修改这个,其余的工作正常。正如彼得建议的那样,我们还可以放置一个Thread.sleep(time);以使 UI 不被阻塞:

UiApplication.getUiApplication().invokeLater(new Runnable() {
    public void run() {
      _listElements.removeAllElements();
        createField();
    }
});
4

1 回答 1

1

我认为您的问题只是您在请求更多数据时没有清除 _listElements Vector。所以 _listElements 只会变得更大。

但是这里有一个更大的问题,那就是您的代码似乎正在事件线程上运行网络操作。你应该在你的 changeListener 中做什么。是启动一个请求数据的线程,然后在此线程获取数据时重新填充 ListField。

由于此更改,UI 不会被阻塞,并且列表更新将变得异步,因此您的用户实际上可以在第一个 Thread 响应返回之前将另一个字符输入到 EditField 中。为了防止这看起来很愚蠢,您可以将线程处理延迟几分之一秒以查看是否输入了另一个字符,和/或您可以确保在重新填充之前 EditField 内容仍然与请求的字符相同。

我个人更喜欢这种异步方法,但如果它困扰您,您可以放置​​一个“请等待 - 加载”类型的屏幕来阻止用户,直到响应返回。

更新

请记住,如果您启动后台线程,则需要返回事件线程来进行 Ui 处理。通常,只需将 UI 代码包含在稍后调用的 Runnable 的 run 方法中即可完成,例如:

UiApplication.getUiApplication().invokeLater(new Runnable() {
  public void run() {
    // Ui Code in here 
  }
});

您应该只将 Ui 更新代码放在可运行文件中。不应包括网络处理或任何其他阻止操作。

于 2013-11-06T12:11:58.363 回答