修改编辑字段上的列表字段更改输入

时间:2013-11-06 11:01:33

标签: list blackberry repaint

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

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

这可以在图片中看到:

enter image description here enter image description here enter image description here

为了实现这个,我写了这段代码:

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

1 个答案:

答案 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更新代码。不应包括网络处理或任何其他阻止操作。