我正在尝试创建一个地震观察器应用程序,但是在加载项目时,我似乎无法从XML URL中获取坐标和其他部分以显示在我的活动中,我知道它们的类型为float。我尝试了不同的方法,但控制台上没有错误,因此它一定与我调用它的方式相同? 我添加了一些输出和图像
package ja.example.mpd1starterearth;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
ListView lvRss;
ArrayList<String> titles;
ArrayList<String> links;
ArrayList<Double> lat;
ArrayList<Double> lon;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvRss = (ListView) findViewById(R.id.lvRss);
titles = new ArrayList<String>();
links = new ArrayList<String>();
lat = new ArrayList<Double>();
lon = new ArrayList<Double>();
lvRss.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Uri uri = Uri.parse(links.get(position));
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
});
new ProcessInBackground().execute();
}
public InputStream getInputStream(URL url)
{
try
{
//openConnection() returns instance that represents a connection to the remote object referred to by the URL
//getInputStream() returns a stream that reads from the open connection
return url.openConnection().getInputStream();
}
catch (IOException e)
{
return null;
}
}
public class ProcessInBackground extends AsyncTask<Integer, Void, Exception>
{
ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);
Exception exception = null;
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog.setMessage("Busy loading rss feed...please wait...");
progressDialog.show();
}
@Override
protected Exception doInBackground(Integer... params) {
try
{
URL url = new URL("http://quakes.bgs.ac.uk/feeds/MhSeismology.xml");
//creates new instance of PullParserFactory that can be used to create XML pull parsers
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
//Specifies whether the parser produced by this factory will provide support
//for XML namespaces
factory.setNamespaceAware(false);
//creates a new instance of a XML pull parser using the currently configured
//factory features
XmlPullParser xpp = factory.newPullParser();
// We will get the XML from an input stream
xpp.setInput(getInputStream(url), "UTF_8");
/* We will parse the XML content looking for the "<title>" tag which appears inside the "<item>" tag.
* We should take into consideration that the rss feed name is also enclosed in a "<title>" tag.
* Every feed begins with these lines: "<channel><title>Feed_Name</title> etc."
* We should skip the "<title>" tag which is a child of "<channel>" tag,
* and take into consideration only the "<title>" tag which is a child of the "<item>" tag
*
* In order to achieve this, we will make use of a boolean variable called "insideItem".
*/
boolean insideItem = false;
// Returns the type of current event: START_TAG, END_TAG, START_DOCUMENT, END_DOCUMENT etc..
int eventType = xpp.getEventType(); //loop control variable
while (eventType != XmlPullParser.END_DOCUMENT)
{
//if we are at a START_TAG (opening tag)
if (eventType == XmlPullParser.START_TAG)
{
//if the tag is called "item"
if (xpp.getName().equalsIgnoreCase("item"))
{
insideItem = true;
}
//if the tag is called "title"
else if (xpp.getName().equalsIgnoreCase("title"))
{
if (insideItem)
{
// extract the text between <title> and </title>
titles.add(xpp.nextText());
}
}
//if the tag is called "link"
else if (xpp.getName().equalsIgnoreCase("link"))
{
if (insideItem)
{
// extract the text between <link> and </link>
links.add(xpp.nextText());
}
}
else if(xpp.getName().equalsIgnoreCase("geo:lat")){
if(insideItem){
//extract the text between <geo:lat> and </geo:lat>
lat.add(Double.valueOf(xpp.nextText()));
}
}
else if(xpp.getName().equalsIgnoreCase("geo:long")){
if(insideItem) {
//extract the text between <geo:lat> and </geo:lat>
lon.add(Double.valueOf(xpp.nextText()));;
} }
}
//if we are at an END_TAG and the END_TAG is called "item"
else if (eventType == XmlPullParser.END_TAG && xpp.getName().equalsIgnoreCase("item"))
{
insideItem = false;
}
eventType = xpp.next(); //move to next element
}
}
catch (MalformedURLException e)
{
exception = e;
}
catch (XmlPullParserException e)
{
exception = e;
}
catch (IOException e)
{
exception = e;
}
return exception;
}
@Override
protected void onPostExecute(Exception s) {
super.onPostExecute(s);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, titles);
lvRss.setAdapter(adapter);
progressDialog.dismiss();
}
}
}
答案 0 :(得分:0)
您正在比较标记名称和其中的空格,因此equalsIgnoreCase()
将始终返回false
,因为geo:lang
将不等于geo :lat
。
只需测试此代码。
String s = "geo:lang";
System.out.println(""+s.equalsIgnoreCase("geo :long"));
对于两种情况,您都需要删除o
和:
之间的空格。equalsIgnoreCase("geo:long")
答案 1 :(得分:0)
您用于解析URL中数据的代码是完全正确的。您不会看到所有活动的所有数据,因为这行代码。
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, titles);
您将titles
数组列表传递给适配器,这就是为什么您仅在活动中看到所有标题xml的原因。
解决方案::简单的方法是格式化从4个数组列表titles
,links
,lat
,lon
连接的数据的格式。 / p>
/**
* This method will format data from titles, links, lat, lon arraylist.
*/
private List<String> formatDataBeforeDisplayOnListView(){
List<String> list = new ArrayList<>();
StringBuilder sb = new StringBuilder();
int size = titles.size();
for (int i = 0; i < size; ++i) {
String title = titles.get(i);
String link = links.get(i);
Double geoLat = lat.get(i);
Double getLon = lon.get(i);
sb.append("title: ").append(title).append("\n")
.append("link: ").append(link).append("\n")
.append("geo-lat: ").append(geoLat).append("\n")
.append("geo-lon: ").append(getLon);
list.add(sb.toString());
}
return list;
}
然后将代码更改为
// Comment-out this line
// ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, titles);
List<String> items = formatDataBeforeDisplayOnListView();
ArrayAdapter<String> adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, items);
注意::如果要在更好的设计/ UI中显示每个项目列表视图,则应编写自定义适配器类,而不要编写ArrayAdapter
。
更新:基于Jase的评论
首先,声明一个名为Item
的新类
public class Item {
private String title;
private String link;
private Double lat;
private Double lon;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public Double getLat() {
return lat;
}
public void setLat(Double lat) {
this.lat = lat;
}
public Double getLon() {
return lon;
}
public void setLon(Double lon) {
this.lon = lon;
}
@Override
public String toString() {
return (new StringBuilder()).append("title: ").append(title).append("\n")
.append("link: ").append(link).append("\n")
.append("geo-lat: ").append(lat).append("\n")
.append("geo-lon: ").append(lon).toString();
}
}
然后,将您的活动代码更改为
public class MainActivity extends AppCompatActivity {
ListView lvRss;
ArrayList<Item> mItems = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvRss = (ListView) findViewById(R.id.lvRss);
lvRss.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// TODO: Process clicked item here
Item item = (Item) parent.getItemAtPosition(position);
Uri uri = Uri.parse(item.getLink());
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
});
new ProcessInBackground().execute();
}
public InputStream getInputStream(URL url) {
try {
//openConnection() returns instance that represents a connection to the remote object referred to by the URL
//getInputStream() returns a stream that reads from the open connection
return url.openConnection().getInputStream();
} catch (IOException e) {
return null;
}
}
public class ProcessInBackground extends AsyncTask<Integer, Void, Exception> {
ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);
Exception exception = null;
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog.setMessage("Busy loading rss feed...please wait...");
progressDialog.show();
}
@Override
protected Exception doInBackground(Integer... params) {
try {
URL url = new URL("http://quakes.bgs.ac.uk/feeds/MhSeismology.xml");
//creates new instance of PullParserFactory that can be used to create XML pull parsers
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
//Specifies whether the parser produced by this factory will provide support
//for XML namespaces
factory.setNamespaceAware(false);
//creates a new instance of a XML pull parser using the currently configured
//factory features
XmlPullParser xpp = factory.newPullParser();
// We will get the XML from an input stream
xpp.setInput(getInputStream(url), "UTF_8");
/* We will parse the XML content looking for the "<title>" tag which appears inside the "<item>" tag.
* We should take into consideration that the rss feed name is also enclosed in a "<title>" tag.
* Every feed begins with these lines: "<channel><title>Feed_Name</title> etc."
* We should skip the "<title>" tag which is a child of "<channel>" tag,
* and take into consideration only the "<title>" tag which is a child of the "<item>" tag
*
* In order to achieve this, we will make use of a boolean variable called "insideItem".
*/
boolean insideItem = false;
// Returns the type of current event: START_TAG, END_TAG, START_DOCUMENT, END_DOCUMENT etc..
int eventType = xpp.getEventType(); //loop control variable
Item item = null;
while (eventType != XmlPullParser.END_DOCUMENT) {
//if we are at a START_TAG (opening tag)
if (eventType == XmlPullParser.START_TAG) {
//if the tag is called "item"
if (xpp.getName().equalsIgnoreCase("item")) {
insideItem = true;
item = new Item();
}
//if the tag is called "title"
else if (xpp.getName().equalsIgnoreCase("title")) {
if (insideItem) {
// extract the text between <title> and </title>
item.setTitle(xpp.nextText());
}
}
//if the tag is called "link"
else if (xpp.getName().equalsIgnoreCase("link")) {
if (insideItem) {
// extract the text between <link> and </link>
item.setLink(xpp.nextText());
}
} else if (xpp.getName().equalsIgnoreCase("geo:lat")) {
if (insideItem) {
//extract the text between <geo:lat> and </geo:lat>
item.setLat(Double.valueOf(xpp.nextText()));
}
} else if (xpp.getName().equalsIgnoreCase("geo:long")) {
if (insideItem) {
//extract the text between <geo:lat> and </geo:lat>
item.setLon(Double.valueOf(xpp.nextText()));
}
}
}
//if we are at an END_TAG and the END_TAG is called "item"
else if (eventType == XmlPullParser.END_TAG && xpp.getName().equalsIgnoreCase("item")) {
insideItem = false;
mItems.add(item);
}
eventType = xpp.next(); //move to next element
}
} catch (MalformedURLException e) {
exception = e;
} catch (XmlPullParserException e) {
exception = e;
} catch (IOException e) {
exception = e;
}
return exception;
}
@Override
protected void onPostExecute(Exception s) {
super.onPostExecute(s);
ArrayAdapter<Item> adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, mItems);
lvRss.setAdapter(adapter);
progressDialog.dismiss();
}
}
}