#android #xml #android-intent #saxparser
#Android #xml #android-намерение #saxparser
Вопрос:
Я работаю над приложением для Android, в котором я буду довольно часто использовать SAX. Мне было интересно, каким был бы наилучший способ отправить «данные» или результаты из моего обработчика обратно в мою activity?
IMO довольно запутанно вызывать intents или создавать тосты и т.д. В моем обработчике, и я бы предпочел делать подобные вещи из моей activity, в зависимости от того, что происходит в моем обработчике.
Что вы, ребята, думаете? Как мне сделать это чистым способом?
Вот пример кода:
public void startElement(String n, String l, String q, Attributes a) throws SAXException{
if(l == "login") in_loginTag = true;
if(l == "error") {
if(Integer.parseInt(a.getValue("value")) == 1)
Toast.makeText(getApplicationContext(), "Couldn't connect to Database", Toast.LENGTH_SHORT).show();
if(Integer.parseInt(a.getValue("value")) == 2)
Toast.makeText(getApplicationContext(), "Error in Database: Table missing", Toast.LENGTH_SHORT).show();
if(Integer.parseInt(a.getValue("value")) == 3)
Toast.makeText(getApplicationContext(), "Invalid username and/or password", Toast.LENGTH_SHORT).show();
error_occured = true;
}
Я бы предпочел не показывать эти тосты из моего класса-обработчика.
Ответ №1:
Я проделал довольно большой синтаксический анализ XML в своем текущем приложении, и этот пример очень помог.
С точки зрения дизайна я полагаю, что вместо тостов или трансляции намерений и т.д. Вы должны использовать пользовательский обработчик SAX, который создаст экземпляр объекта Parse в начальном элементе XML. Этот объект является представлением ваших XML-элементов. Так что, возможно, объектом будет Car и у него будет параметр setter / getter для двери, цвета, колес. При анализе данных в анализаторе SAX вы будете устанавливать эти значения. когда анализатор SAX завершает синтаксический анализ, вы вызываете свой анализатор, чтобы он передал обратно объект в вашу activity, который заполнен всеми машинами из вашего XML. В моем случае я фактически заполняю список / массив своих объектов, которые передаются обратно. В примере рассматривается только один набор данных. В любом случае, эта ссылка все объясняет.
Редактировать: просто просматривал свой код, на самом деле, что я делаю в своем обработчике, так это создаю массив моих объектов ParsedData set, которые передаются обратно в activity после завершения синтаксического анализа через getParsedData(). Вот некоторые важные коды:
Обработчик XML:
private boolean in_IdSite;
private boolean in_SiteName;
private ArrayList<ParsedChannelDataSet> list = new ArrayList<ParsedChannelDataSet>();
public ArrayList<ParsedChannelDataSet> getParsedData() {
return this.list;
}
@Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
// first tag parsed so add a new ParsedEventDataSet object
if(localName.equals("stmSiteUser")) {
list.add(new ParsedChannelDataSet());
} else if (localName.equals("idSite")) {
this.in_IdSite = true;
} else if (localName.equals("siteName")) {
this.in_SiteName = true;
}
}
@Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
if (localName.equals("idSite")) {
this.in_IdSite = false;
} else if (localName.equals("siteName")) {
this.in_SiteName = false;
}
}
@Override
public void characters(char ch[], int start, int length) {
// determine if any tag is current, get data from tag and populate into ParsedEventDataSet
if (this.in_IdSite) {
this.list.get(this.list.size()-1).setExtractedIdSite(new String(ch, start, length));
} else if (this.in_SiteName) {
this.list.get(this.list.size()-1).setExtractedSiteName(new String(ch, start, length));
}
}
Вот мой пример ParsedDataSampleSet (это можно называть как угодно) очевидно, вы хотите заменить siteName и idSite чем-то другим. Это всего лишь мои XML-элементы
public class ParsedChannelDataSet {
private String extractedIdSite = null;
private String extractedSiteName = null;
public String getExtractedIdSite() {
return extractedIdSite;
}
public void setExtractedIdSite(String _extractedIdSite) {
this.extractedIdSite = _extractedIdSite;
}
public String getExtractedSiteName() {
return extractedSiteName;
}
public void setExtractedSiteName(String _extractedSiteName) {
Log.d("", _extractedSiteName);
this.extractedSiteName = _extractedSiteName;
}
public String toString() {
/* TODO */
return "todo";
}
}
Итак, вы можете видеть, что я создаю массив объектов ParsedChannelDataSet, которые передаются обратно в activity. это гораздо лучшее решение, чем использование тостов или трансляций, потому что это более развязанное решение
Редактировать 2: В первом сообщении на этой 2-й странице сайта, на который я ссылался, упоминается о разборе нескольких XML-элементов, подобных моему. Смотрите здесь (разбор нескольких XML-элементов).
Я надеюсь, что это поможет вам
Комментарии:
1. Я уже видел этот пример раньше, но только бегло просмотрел его. Я, вероятно, воспользуюсь этим подходом. Спасибо!
2. Я только что добавил несколько примеров кода, я понял, что на самом деле я создаю массив моих проанализированных объектов внутри обработчика, чего, я думаю, в этом примере нет.
3. Что именно такое
ParsedChannelDataSet
, я ничего не могу найти об этом в Google. Кроме того, что именно он содержит здесь?list.add(new ParsedChannelDataSet());
Или вы считаете только свойstmSiteUser
или что-то в этом роде?4. это просто класс, который вы используете, вы можете называть его как хотите. Мой называется ParsedChannelDataSet (поскольку мой XML представляет собой список каналов), вы можете назвать его ParsedCarDataSet. На самом деле это просто объект для хранения каждого элемента XML. В этом примере вы хотите посмотреть на «/src/your_package_structure/ParsedExampleDataSet.java » anddev.org /…
5. о, извините, да, пропустил тот комментарий о list.add(new ParsedCHannelDataSet()); именно, да. Когда обработчик XML достигает начального элемента в моем случае <stmSiteUser>, он вызывает обратный вызов startElement(), который добавит пустой объект в мой список. Затем при достижении обратного вызова символов он заполняет объект с помощью setExtractedSiteId(), setExtractedSiteName() и т.д.. все, что вам нужно
Ответ №2:
Вы могли бы:
-
Передайте activity в обработчик XML, сохраните его как переменную экземпляра и при необходимости вызывайте к нему обратный вызов.
-
Создайте статический элемент в своем activity и назначьте ему activity при его создании. Затем из вашего XML-обработчика вы могли бы сослаться на ActivityClass.getMyActivity() [например] и вызвать какой-либо метод для всплывающего окна toast.
В iOS / Mac OS X есть концепция, называемая «уведомления», где любой код может зарегистрировать интерес к некоторому событию. Если есть эквивалент Android, это был бы другой способ сделать это, т. е. обработчик XML мог бы транслировать какое-то событие сбоя / уведомление, и Activity могла бы его прослушать и всплыть.
Комментарии:
1. Из того, что я понял, используемые уведомления в стиле iOS, как вы описываете, будут являться намерением трансляции Android с получателем, зарегистрированным в activity?
2. Похоже на то. К сожалению, похоже, что вам потребуется доступ к контексту для отправки широковещательного события, что, я полагаю, требует некоторой работы, подобной моему решению (2), чтобы сделать контекст доступным для обработчика XML.
Ответ №3:
Я бы использовал пользовательский, Handler
который я создал в своей activity, и передал его в анализатор XML. Затем в этом анализаторе я мог бы вызвать некоторые sendMessage
из пользовательского обработчика.
Здесь приведен пример использования обработчика.