I'm trying to populate a ListView with the data obtained using HTTP POST URL, the data received is a XML document like this:
<?xml version="1.0" encoding="utf-8" ?>
- <Arrives>
- <Arrive>
<IdStop>226</IdStop>
<idLine>70</idLine>
<IsHead>True</IsHead>
<Destination>ALSACIA</Destination>
<IdBus>0000</IdBus>
<TimeLeftBus>0</TimeLeftBus>
<DistanceBus>373</DistanceBus>
<PositionXBus>-1</PositionXBus>
<PositionYBus>-1</PositionYBus>
<PositionTypeBus>2</PositionTypeBus>
</Arrive>
- <Arrive>
<IdStop>226</IdStop>
<idLine>11</idLine>
<IsHead>True</IsHead>
<Destination>BARRIO BLANCO</Destination>
<IdBus>0000</IdBus>
<TimeLeftBus>161</TimeLeftBus>
<DistanceBus>1498</DistanceBus>
<PositionXBus>-1</PositionXBus>
<PositionYBus>-1</PositionYBus>
<PositionTypeBus>1</PositionTypeBus>
</Arrive>
- <Arrive>
<IdStop>226</IdStop>
<idLine>N3</idLine>
<IsHead>True</IsHead>
<Destination>CIBELES</Destination>
<IdBus>0000</IdBus>
<TimeLeftBus>422</TimeLeftBus>
<DistanceBus>1923</DistanceBus>
<PositionXBus>-1</PositionXBus>
<PositionYBus>-1</PositionYBus>
<PositionTypeBus>1</PositionTypeBus>
</Arrive>
</Arrives>
The only tags which I need to use in ListView are idLine, Destination and TimeLeftBus.
The method I planned to use in HTTP Request: (I can do this using GET METHOD too)
public void postData() {
// Create a new HttpClient and Post Header
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("SITE URL");
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
nameValuePairs.add(new BasicNameValuePair("apiid", "API ID"));
nameValuePairs.add(new BasicNameValuePair("apikey", "API KEY"));
nameValuePairs.add(new BasicNameValuePair("stopid", "STOP ID"));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
} catch (ClientProtocolException e) {
// TODO Log exception
} catch (IOException e) {
// TODO Log exception
}
}
How can implement this? Thanks for your help.
I'm not really familiar with obtaining data from an HTTP POST URL but I do know how to get your xml data to your list view. What I would do is
Create an object to encapsulate idLine, Destination and TimeLeftBus
Use an xml parser to return a list of those objects
Create a custom adapter (if necessary) to populate your list view.
See the code below for each of these steps.
Step 1:
public class ArrivalInfo {
private String idLine;
private String destination;
private String timeLeft;
public void setIdLine(String id) {
this.idLine = id;
}
public String getIdLine() {
return idLine;
}
...(getters and setters for other fields)
}
Step 2:
public class XMLParser {
//the tags as found in your XML document
private static final String ARRIVE = "arrive";
private static final String ID_LINE = "idLine";
private static final String DEST = "Destination";
private static final String TIME_LEFT_BUS = "TimeLeftBus";
private ArrivalInfo curArrival = null;
List<ArrivalInfo> arrivals = new ArrayList<ArrivalInfo>();
public List<ArrivalInfo> getArrivals() {
return arrivals;
}
public void parseXml() {
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
InputStream stream = getResources().openRawResource(...) (this can be done in different
ways depending on where the file is)
int eventType = xpp.getEventType();
while(eventType != XmlPullParser.END_DOCUMENT) {
if(eventType == XmlPullParser.START_TAG) {
handleStartTag(xpp.getName());
}
else if (eventType == XmlPullParser.END_TAG) {
handleEndTag(xpp.getName());
}
else if (eventType == XmlPullParser.TEXT) {
handleText(xpp.getName(), xpp.getText());
}
eventType = xpp.next();
} catch(NotFoundException e) {
...handle exeptions
}
public void handleStartTag(String tag) {
if(tag.equalsIgnoreCase(ARRIVE)) {
curArrival = new ArrivalInfo();
}
}
public void handleEndTag(String tag) {
if(tag.equalsIgnoreCase(ARRIVE)) {
arrivals.add(curArrival);
}
}
public void handleText(String tag, String text) {
if(curArrival != null) {
if(tag.equalsIgnoreCase(ID_LINE)) {
curArrival.setIdLine(text);
}
else if (tag.equalsIgnoreCase(DEST)) {
curArrival.setDestination(text);
}
// and so on...
}
}
} //end of XmlParser
Step 3: (This would happen in a non UI thread, i.e. use an AsyncTask to do this on a different thread);
public class MyActivity extends Activity {
private ListView mListView;
private StableArrayAdapter adapter;
private List<ArrivalInfo> arrivals;
private class LoadDataTask extends AsyncTask<Void, Void, List<ArrivalInfo>>() {
#Override
public void doInBackground(Void...params) {
XmlParser parser = new XmlParser();
try {
parser.parseXml();
} finally {
return parser.getArrivals();
}
}
#Override
public void onPostExecute(List<ArrivalInfo> list) {
if(mListView != null && adapter != null) {
arrivals = list;
adapter.notifyDataSetChanged();
}
}
} // end of loading task.
#Override
public void onCreate(Bundle savedInstanceState) {
arrivals = new ArrayList<ArrivalInfo>();
setContentView(R.layout.my_layout);
mListView = findViewById(android.R.id.list);
StableArrayAdapter adapter = new StableArrayAdapter(this,
android.R.layout.simple_list_item_1, arrivals);
mListView.setAdapter(adapter);
new LoadDataTask().execute();
}
} // end of your activity
And that's pretty much it! hope that helps you do what you want to do.
Related
I am getting NetworkonMainThreadException sometime.I dont know what is the problem. First time it opens with no error, But after few times closing and opening cause the NetworkOnMainThreadException.
Below is my MainActivity
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new DownloadWebpageTask().execute();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private class DownloadWebpageTask extends AsyncTask<String, Void, String> {
List<Member> members = new ArrayList<Member>();
ListView listView = (ListView) findViewById(R.id.listView1);
String ss = "";
InputStream is;
HttpURLConnection connection ;
#Override
protected String doInBackground(String... urls) {
try {
URL url = new URL("http://192.168.1.107:8080/SEWS_webservice/rest/members");
connection = (HttpURLConnection) url.openConnection();
is = connection.getInputStream();
} catch (IOException e) {
System.out.println(e+"***********************&&&&&&&&&&&&&");
}finally {
connection.disconnect();
}
return ss;
}
// onPostExecute displays the results of the AsyncTask.
#Override
protected void onPostExecute(String result) {
XmlPullParserHandler parser = new XmlPullParserHandler();
parser.parse(is);
members = parser.getMembers();
ArrayAdapter<Member> adapter = new ArrayAdapter<Member>(getApplicationContext(),android.R.layout.simple_list_item_1, members);
listView.setAdapter(adapter);
}
}
}
This is XMLPullParser handler
public class XmlPullParserHandler {
private List<Member> members= new ArrayList<Member>();
private Member member;
private String text;
public List<Member> getMembers() {
return members;
}
public List<Member> parse(InputStream is) {
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser parser = factory.newPullParser();
parser.setInput(is, null);
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
String tagname = parser.getName();
switch (eventType) {
case XmlPullParser.START_TAG:
if (tagname.equalsIgnoreCase("member")) {
// create a new instance of employee
member = new Member();
}
break;
case XmlPullParser.TEXT:
text = parser.getText();
break;
case XmlPullParser.END_TAG:
if (tagname.equalsIgnoreCase("member")) {
// add employee object to list
members.add(member);
}else if (tagname.equalsIgnoreCase("memberId")) {
member.setMemberId(Integer.parseInt(text));
}
else if (tagname.equalsIgnoreCase("firstName")) {
member.setFirstName(text);
}
else if (tagname.equalsIgnoreCase("middleName")) {
member.setMiddleName(text);
}
else if (tagname.equalsIgnoreCase("lastName")) {
member.setLastName(text);
}
break;
default:
break;
}
eventType = parser.next();
}
} catch (XmlPullParserException e) {e.printStackTrace();}
catch (IOException e) {e.printStackTrace();}
return members;
}
}
The problem is even though you are connecting up to the website properly in the background you are reading from the underlying socket using the InputStream. You need to refactor your solution so that you are returning a String or raw data from your InputStream as the result of doInBackground and closing out any http connections. Something like
#Override
protected String doInBackground(String... urls) {
try {
URL url = new URL("http://192.168.1.107:8080/SEWS_webservice/rest/members");
connection = (HttpURLConnection) url.openConnection();
is = connection.getInputStream();
ByteArrayOutputStream oStream = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
int numRead = -1;
while ((numRead = (is.read(buffer))) > -1) {
oStream.write(buffer, 0, numRead);
}
return new String(oStream.getBytes(), "UTF-8");
} catch (IOException e) {
System.out.println(e+"***********************&&&&&&&&&&&&&");
}finally {
connection.disconnect();
}
return ss;
}
// onPostExecute displays the results of the AsyncTask.
#Override
protected void onPostExecute(String result) {
XmlPullParserHandler parser = new XmlPullParserHandler();
parser.parse(result);
members = parser.getMembers();
ArrayAdapter<Member> adapter = new ArrayAdapter<Member>(getApplicationContext(),android.R.layout.simple_list_item_1, members);
listView.setAdapter(adapter);
}
Should do it if the XmlPullParserHandler can read Strings, otherwise that too will need to get moved to the background portion.
Seems like XmlPullParser doesn't like to work on UI thread :)
I could not find exact proves of this, but even official example makes it work in AsyncTask.
In your case just try to move next lines:
XmlPullParserHandler parser = new XmlPullParserHandler();
parser.parse(is);
members = parser.getMembers();
into doInBackground() method and check the result.
PS. Not relating to question, but what is purpose of this String ss = "";?
You can change AsyncTask<String, Void, String> to AsyncTask<String, Void, Void> if you don't want to return anything.
Or, better way, - you can do this AsyncTask<String, Void, List<Member>>.
Then you make protected void onPostExecute(List<Member> result) and use this result in your Adapter code.
I have used AsyncTask with Activity, And it gave me desired result without any failure.
Now I need to use AsyncTask with Fragments. In Fragments AsyncTask is not updating UI. I got an answer here. I tried that logic in my code but still I'm not able to update UI after getting response from servlet. Your help will be very appreciated.
Code what I have tried:
public class FragmentMyProfile extends Fragment
{
TextView txtViewUserFullName;
SharedPreferences shrdPref;
String currentUserFirstName = "", currentUserEmail = "";
String URL = "http://10.0.2.2:8080/iGnite_Survey/GetUserDetailsServlet";
String jsonObjectReceivedFromServer = "";
public FragmentMyProfile()
{
// empty constructor required for fragment subclass
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.fragment_my_profile, container, false);
shrdPref = rootView.getContext().getSharedPreferences("shrdPref", Context.MODE_PRIVATE);
txtViewUserFullName = (TextView) rootView.findViewById(R.id.textViewUserFullName);
//get current user first name, default value is ""
currentUserFirstName = shrdPref.getString(String.valueOf(R.string.curentLoggedInUserFirstName), "");
currentUserEmail = shrdPref.getString(String.valueOf(R.string.curentLoggedInUserEmail), "");
//display current user first name
if(!currentUserFirstName.equals(""))
{
txtViewDisplayUserFirstName.setText("Welcome "+currentUserFirstName);
}
else
{
txtViewDisplayUserFirstName.setText(String.valueOf(R.string.welcomeUser));
}
//get all user details from server
GetUserDetailsAsyncTask getUserDetailsAsyncTask = new GetUserDetailsAsyncTask (new FragmentCallback()
{
#Override
public void onTaskDone(String output)
{
//txtViewUserFullName.setText(output);
}
});
getUserDetailsAsyncTask.execute(new String[] { URL });
return rootView;
}
public interface FragmentCallback
{
public void onTaskDone(String output);
}
//------------------------------------------------------------------------------
public class GetUserDetailsAsyncTask extends AsyncTask<String, Void, String>
{
private FragmentCallback mFragmentCallback;
public GetUserDetailsAsyncTask (FragmentCallback fragmentCallback)
{
mFragmentCallback = fragmentCallback;
}
#Override
protected String doInBackground(String... urls)
{
String output = null;
for (String url : urls)
{
output = sendDataToServer(url);
}
return output;
}
#Override
protected void onPostExecute (String output)
{
super.onPostExecute(output);
mFragmentCallback.onTaskDone();
txtViewUserFullName.setText("output");
}
private String sendDataToServer(String url)
{
String output = null;
try
{
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("user_email", currentUserEmail));
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpClient.execute(httpPost);
HttpEntity httpEntity = response.getEntity();
output = EntityUtils.toString(httpEntity);
}
catch (ClientProtocolException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
return output;
}
}
}
You have to use the inter-fragment communication concept to update the UI Thread from the fragment asynctask i.e INTERFACE
Please refer this tutorial with source code to understand it better : Handle Android AsyncTask Configuration Change Using Fragment
Hi and thanks for your help.
I am parsing an XML that I retrieve from an URL.
But when I call the parser after some seconds I crash and get an java.lang.NullPointerException
In particular, this is the code:
public class AndroidXMLParsingActivity extends Activity {
// All static variables
static final String URL = "http://www.nation.co.ke/news.xml";
public ArrayList<Article> articoli;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ListView lv = (ListView) findViewById(R.id.list);
String xml = getXmlFromUrl(URL);
InputSource source = new InputSource(new StringReader(xml));
try {
articoli = ReadXMLFileUsingSaxparser.parsa(source);
} catch (Exception e) {
Log.e("ERRROR", e.toString());
}
ListAdapter adapter = new NewsAdapter(this, articoli);
lv.setAdapter(adapter);
}
public static String getXmlFromUrl(String url) {
String xml = null;
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
xml = EntityUtils.toString(httpEntity);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// return XML
return xml;
}
}
Well articoli returns null form the call to ReadXMLFileUsingSaxparser.parsa(source)
This is the code of the parser.
public class ReadXMLFileUsingSaxparser extends DefaultHandler {
private Article acct;
private String temp;
private static ArrayList<Article> accList = new ArrayList<Article>();
/** The main method sets things up for parsing */
public static ArrayList<Article> parsa(InputSource xml) throws IOException, SAXException,
ParserConfigurationException {
//Create a "parser factory" for creating SAX parsers
SAXParserFactory spfac = SAXParserFactory.newInstance();
//Now use the parser factory to create a SAXParser object
SAXParser sp = spfac.newSAXParser();
//Create an instance of this class; it defines all the handler methods
ReadXMLFileUsingSaxparser handler = new ReadXMLFileUsingSaxparser();
//Finally, tell the parser to parse the input and notify the handler
sp.parse(xml, handler);
handler.readList();
return accList;
}
/*
* When the parser encounters plain text (not XML elements),
* it calls(this method, which accumulates them in a string buffer
*/
public void characters(char[] buffer, int start, int length) {
temp = new String(buffer, start, length);
}
/*
* Every time the parser encounters the beginning of a new element,
* it calls this method, which resets the string buffer
*/
public void startElement(String uri, String localName,
String qName, Attributes attributes) throws SAXException {
temp = "";
if (qName.equalsIgnoreCase("item")) {
acct = new Article();
}
}
/*
* When the parser encounters the end of an element, it calls this method
*/
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (qName.equalsIgnoreCase("item")) {
// add it to the list
accList.add(acct);
} else if (qName.equalsIgnoreCase("title")) {
acct.title=temp;
} else if (qName.equalsIgnoreCase("description")) {
acct.description=temp;
} else if (qName.equalsIgnoreCase("articleDate")) {
acct.articleDate=temp;
} else if (qName.equalsIgnoreCase("story")) {
acct.story=temp;
} else if (qName.equalsIgnoreCase("author")) {
acct.author=temp;
} else if (qName.equalsIgnoreCase("photo")) {
acct.photo=temp;
} else if (qName.equalsIgnoreCase("caption")) {
acct.caption=temp;
} else if (qName.equalsIgnoreCase("link")) {
acct.link=temp;
} else if (qName.equalsIgnoreCase("video")) {
acct.video=temp;
}
}
private void readList() {
Log.e("","No of the accounts in bank '" + accList.size() + "'.");
Iterator<Article> it = accList.iterator();
int i=0;
while (it.hasNext()) {
Log.e("STORY " + Integer.toString(i),it.next().story);
i++;
}
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ListView lv = (ListView) findViewById(R.id.list);
String xml = getXmlFromUrl(URL);
InputSource source = new InputSource(new StringReader(xml));
try {
articoli = ReadXMLFileUsingSaxparser.parsa(source);
} catch (Exception e) {
Log.e("ERRROR", e.toString());
}
if(articoli != null){
ListAdapter adapter = new NewsAdapter(this, articoli);
lv.setAdapter(adapter);
}
else{
// TODO: show message to the user about xml data is invalid or you have network connection error or so on
finish(); // return to the previous Activity.
}
}
Here example is there. http://androidcodesnips.blogspot.com/2011/04/sax-parsing.html
which will help you setup a sax parser for xml
My guess is that you are running into the NullPointer when
try {
articoli = ReadXMLFileUsingSaxparser.parsa(source);
} catch (Exception e) {
Log.e("ERRROR", e.toString());
}
ListAdapter adapter = new NewsAdapter(this, articoli);
lv.setAdapter(adapter);
fails so that you initialize your ListView with an adapter that is null.
Simply initialize the articoli ArrayList inside the catch block, avoid crashes inside the Parser or make an != null check.
I'm currently using XMLPullParser to parse a page from a train station API. I'm doing this using Async task as to keep up with the newer versions of android.
Currently I have hardcoded the XML string into the class and the results display out in a listview.
However, I am having trouble appending the baseURL to add a user inputted query to the end of it. I had no trouble doing this before using Async Tasks using code along these lines:
public void StationDetails(){
//--- Search button ---
Button btnSearch = (Button) findViewById(R.id.btnSearch);
btnSearch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//--- EditText View ---
EditText input = (EditText) findViewById(R.id.inputStation);
StringBuilder URL = new StringBuilder(baseURL);
URL.append(input);
String fullURL = URL.toString();
}
});
}
But I cannot relate this into the Async Method. I can't seem to find anything online and would really appreciate anyones help in this matter.
Here is the class with the hardcodes string:
public class Realtime extends Activity {
// Irish Rail Site URL
private static final String baseURL = "http://api.irishrail.ie/realtime/realtime.asmx/getStationDataByNameXML?StationDesc=Malahide";
// XML TAG Name
private static final String TAG_ITEM = "objStationData";
private static final String TAG_ORIGIN = "Origin";
private static final String TAG_DEST = "Destination";
private static final String TAG_SCHARR = "Scharrival";
private static final String TAG_EXPARR = "Exparrival";
private static final String TAG_DIRECT = "Direction";
private static final String TAG_STAT = "Status";
private static final String TAG_TRAINTYPE = "Traintype";
private RealtimeListviewAdapter mAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.stations_realtime_layout);
ListView listView = (ListView) findViewById(R.id.listview);
mAdapter = new RealtimeListviewAdapter(this);
// set adapter
listView.setAdapter(mAdapter);
// use AsyncTask to parse the URL data
ParseTask task = new ParseTask(this);
task.execute(baseURL);
// --- Register the list view for long press menu options
registerForContextMenu(listView);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private class ParseTask extends
AsyncTask<String, Void, ArrayList<StationDetails>> {
private ProgressDialog dialog;
public ParseTask(Context c) {
dialog = new ProgressDialog(c);
}
#Override
protected void onPreExecute() {
dialog.setMessage("Loading Station Info...");
dialog.show();
}
#Override
protected ArrayList<StationDetails> doInBackground(String... params) {
String strUrl = params[0];
HttpURLConnection httpConnection = null;
InputStream is = null;
try {
URL url = new URL(strUrl);
httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setRequestMethod("GET");
httpConnection.setConnectTimeout(10000);
httpConnection.setReadTimeout(10000);
httpConnection.connect();
int responseCode = httpConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
is = httpConnection.getInputStream();
return parseNews(is);
}
} catch (Exception e) {
// TODO
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (httpConnection != null) {
httpConnection.disconnect();
httpConnection = null;
}
}
return null;
}
#Override
protected void onPostExecute(ArrayList<StationDetails> result) {
// set the result
mAdapter.setData(result);
// notify to refresh
mAdapter.notifyDataSetChanged();
// Close the progress dialog
if (dialog.isShowing()) {
dialog.dismiss();
}
}
}
private ArrayList<StationDetails> parseNews(InputStream in)
throws XmlPullParserException, IOException {
ArrayList<StationDetails> newsList = new ArrayList<StationDetails>();
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser pullParser = factory.newPullParser();
pullParser.setInput(in, "UTF-8");
int eventType = pullParser.getEventType();
StationDetails item = null;
while (eventType != XmlPullParser.END_DOCUMENT) {
String tagName;
if (eventType == XmlPullParser.START_TAG) {
tagName = pullParser.getName();
if (tagName.equals(TAG_ITEM)) {
item = new StationDetails();
} else if (tagName.equals(TAG_ORIGIN)) {
if (item != null) {
item.mOrigin = pullParser.nextText();
}
} else if (tagName.equals(TAG_DEST)) {
if (item != null) {
item.mDestination = pullParser.nextText();
}
} else if (tagName.equals(TAG_SCHARR)) {
if (item != null) {
item.mSchArrival = pullParser.nextText();
}
} else if (tagName.equals(TAG_EXPARR)) {
if (item != null) {
item.mExpArrival = pullParser.nextText();
}
} else if (tagName.equals(TAG_DIRECT)) {
if (item != null) {
item.mDirection = pullParser.nextText();
}
} else if (tagName.equals(TAG_STAT)) {
if (item != null) {
item.mStatus = pullParser.nextText();
}
}
} else if (eventType == XmlPullParser.END_TAG) {
tagName = pullParser.getName();
if (tagName.equals(TAG_ITEM)) {
newsList.add(item);
item = null;
}
}
eventType = pullParser.next();
}
return newsList;
}
EDIT UPDATE
Ok I put the stringbuilder for the fullURL in an onClickListener for a button. Now what I want is to execute the task when the button is clicked. I moved the parsetask task, .excute etc into this clickListener. However this gives me an error saying that the View.OnClickListener for realtime is undefined, i follow the quick fixes, but then when running the porject I get an error in the logcat saying cannot be cast to android.content.Context.
Heres a snippet of what the code looks like now after the quick fix
searchBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Append user input to baseURL
StringBuilder URL = new StringBuilder(baseURL);
URL.append(userInput);
String fullURL = URL.toString();
// use AsyncTask to parse the URL data
ParseTask task = new ParseTask(this);
task.execute(fullURL);
}
});
public ParseTask(OnClickListener onClickListener) {
dialog = new ProgressDialog((Context) onClickListener);
}
and my logcat:
I still can't figure this out and anybodys help would be very welcom
Why won't you just send the full URL to the AsyncTask? Would look something like:
StringBuilder URL = new StringBuilder(baseURL);
URL.append(input);
String fullURL = URL.toString();// use AsyncTask to parse the URL data
ParseTask task = new ParseTask(this);
task.execute(fullURL);
OK problem solved.
What happened was I wasn't taking the userinput and appending it to the URL properly. Love how things are so simple some times. And I also used Realtime.this as Gleb suggested. Thanks for your help. Heres the code in the onClickListener that works...
searchBtn.setOnClickListener(new View.OnClickListener() {
private String userInput;
#Override
public void onClick(View v) {
ListView listView = (ListView) findViewById(R.id.listview);
mAdapter = new RealtimeListviewAdapter(Realtime.this);
//set adapter
listView.setAdapter(mAdapter);
StringBuilder URL = new StringBuilder(baseURL);
etStation = (EditText) findViewById(R.id.inputStation);
userInput = etStation.getText().toString();
URL.append(userInput);
String fullURL = URL.toString();
//use AsyncTask to parse the RSS data
ParseTask task = new ParseTask(Realtime.this);
task.execute(fullURL);
}
});
I tried the code below and also tried the AsyncTaskLoader approach. The app crashes when I instantiate the AsyncTask. Pleas advise me on the best approach to load JSON in a list fragment inside tab host.
The code below is the tab fragment (I use action bar tabs in main activity):
public class TabTop extends ListFragment {
Context context = getActivity().getBaseContext();
String API_URL = "http://api.rottentomatoes.com/api/public/v1.0/movies/770672122/similar.json?apikey=crhhxb4accwwa6cy6fxrm8vj&limit=1";
ArrayList<Deal> deals;
DealsListAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
#SuppressWarnings("unused")
int a = 0;
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
GetTopDeals getTopDeals = new GetTopDeals(context);
getTopDeals.execute(API_URL);
super.onActivityCreated(savedInstanceState);
}
class GetTopDeals extends AsyncTask<String, Void, ArrayList<Deal>>{
ProgressDialog progressDialog;
public GetTopDeals(Context activity) {
this.progressDialog = new ProgressDialog(activity);
}
#Override
protected void onPostExecute(ArrayList<Deal> result) {
adapter = new DealsListAdapter(context, result);
setListAdapter(adapter);
super.onPostExecute(result);
}
#Override
protected void onPreExecute() {
progressDialog.setCancelable(true);
progressDialog.setProgress(0);
progressDialog.setMessage("loading Top deals...");
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
super.onPreExecute();
}
#Override
protected ArrayList<Deal> doInBackground(String... urls) {
String response = sendRequest(urls[0]); // make request for json
return processResponse(response); // parse the Json and return ArrayList to postExecute
}
private String sendRequest(String apiUrl) {
BufferedReader input = null; // get the json
HttpURLConnection httpCon = null; // the http connection object
StringBuilder response = new StringBuilder(); // hold all the data from the jason in string separated with "\n"
try {
URL url = new URL(apiUrl);
httpCon = (HttpURLConnection) url.openConnection();
if (httpCon.getResponseCode() != HttpURLConnection.HTTP_OK) { // check for connectivity with server
return null;
}
input = new BufferedReader(new InputStreamReader(httpCon.getInputStream())); // pull all the json from the site
String line;
while ((line = input.readLine()) != null) {
response.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (httpCon != null) {
httpCon.disconnect();
}
}
return response.toString();
}
}
public ArrayList<Deal> processResponse(String response) {
try {
JSONObject responseObject = new JSONObject(response); // Creates a new JSONObject with name/value mappings from the JSON string.
JSONArray results = responseObject.getJSONArray("movies"); // Returns the value mapped by name if it exists and is a JSONArray.
deals = new ArrayList<Deal>();
for (int i = 0; i < results.length(); i++) { // in this loop i copy the json array to movies arraylist in order to display listView
JSONObject jMovie = results.getJSONObject(i);
int api_id = jMovie.getInt("id");
String name = jMovie.getString("title");
String content = jMovie.getString("synopsis");
JSONObject posters = jMovie.getJSONObject("posters");
String image_url = posters.getString("profile");
}
}catch (JSONException e) {
e.printStackTrace();
}
return deals;
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = new Intent(getActivity().getBaseContext(), DealInformation.class);
startActivity(intent);
super.onListItemClick(l, v, position, id);
}
}
Make your asynctask in his own file.
And when your asynctask is finish, implement OnPostExecute which is automatically call. Notify your adapter by a notifyDataSetChanged like that :
#Override
protected void onPostExecute(List<NewItem> list) {
Adapter.getListe().clear();
Adapter.getListe().addAll(list);
Adapter.notifyDataSetChanged();
}
thank you guys,
i want to post my answer. after some research i decided to go with AsyncTaskLoader.
this is my code
public class TabOurPicks extends ListFragment implements LoaderCallbacks<String[]> {
// when activity loads- onActivityCreated() calls the initLoader() who activate onCreateLoader()
#Override
public void onActivityCreated(Bundle savedInstance) {
super.onActivityCreated(savedInstance);
setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, new String[]{}));
getLoaderManager().initLoader(0, null,this).forceLoad();
}
// onCreateLoader instantiate the asynctaskloaser who work in bg
#Override
public RSSLoader onCreateLoader(int arg0, Bundle arg1) {
return new RSSLoader(getActivity()); //
}
// after bg process invoke onLoadFinished() who work in ui thread
#Override
public void onLoadFinished(Loader<String[]> loader, String[] data) {
setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, data
) );
}
#Override
public void onLoaderReset(Loader<String[]> arg0) {
// TODO Auto-generated method stub
}
and this is the inner class for the loader:
static public class RSSLoader extends AsyncTaskLoader<String[]>
{
public RSSLoader(Context context) {
super(context);
}
#Override
public String[] loadInBackground() {
String url = "http://api.rottentomatoes.com/api/public/v1.0/movies/770672122/similar.json?apikey=crhhxb4accwwa6cy6fxrm8vj&limit=1";
String response = sendRequest(url);
return processResponse(response);
}
private String sendRequest(String url) {
BufferedReader input = null; // get the json
HttpURLConnection httpCon = null; // the http connection object
StringBuilder response = new StringBuilder(); // hold all the data from the jason in string separated with "\n"
try {
URL apiUrl = new URL(url);
httpCon = (HttpURLConnection) apiUrl.openConnection();
if (httpCon.getResponseCode() != HttpURLConnection.HTTP_OK) { // check for connectivity with server
return null;
}
input = new BufferedReader(new InputStreamReader(httpCon.getInputStream())); // pull all the json from the site
String line;
while ((line = input.readLine()) != null) {
response.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (httpCon != null) {
httpCon.disconnect();
}
}
return response.toString();
}
private String[] processResponse(String response) {
String[] deals = null;
try {
JSONObject responseObject = new JSONObject(response); // Creates a new JSONObject with name/value mappings from the JSON string.
JSONArray results = responseObject.getJSONArray("movies"); // Returns the value mapped by name if it exists and is a JSONArray.
deals = new String[10];
for (int i = 0; i < 9; i++) { // in this loop i copy the json array to movies arraylist in order to display listView
JSONObject jMovie = results.getJSONObject(i);
String name = jMovie.getString("title");
deals[i] = name;
}
}catch (JSONException e) {
e.printStackTrace();
}
return deals;
}
}
}
It doesn't matter if your asynctask has its own file. You just don't want your activity to extends asynctask as this would make your activity asynchronous - but this is impossible to do anyways due to java's double inheritance rule.
Based on the architecture of your app and your programming style the asyntask can be an inner class in the activity. on the PostExecute method make sure you have given data to your adapter and that the adapter is set to the list, then just run notifyDataSetChanged().
Assuming your asynctask is loading data from cache or the network you are on the right track with your approach to this.