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);
}
});
Related
I am new in android and am working with a project that loads data from internet into listview. I got my prototype here: kaleidosblog.com/android-listview-load-data-from-json
So these will be the json links:
http://www.funtrial.com/christiancepe/announcements/json.php?page=1
http://www.funtrial.com/christiancepe/announcements/json.php?page=2
So on..
In my activity, I have my EditText, Button and ListView.
Editext will get the url.
Button will be use to load the json link (from url) to listview
Listview will display datas
In my current program, it only works on first click of button. So once I entered the first json, it will show the correct data. But when I try to change the json on EditText, still the ListView is populated by the first json. In short, my ListView does not refresh everytime I am changing the link and clicking the button.
What's wrong with this?
Main Activity:
protected void onCreate(Bundle savedInstanceState) {
final Button searchButton = (Button) findViewById(R.id.searchButton);
final EditText searchForm = (EditText) findViewById(R.id.searchForm);
searchButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
list = (ListView) findViewById(R.id.list);
adapter = new ListAdapter(MainActivity.this);
list.setAdapter(adapter);
search = searchForm.getText().toString();
Download_data download_data = new Download_data((download_complete) MainActivity.this);
download_data.download_data_from_link(search);
adapter.notifyDataSetChanged();
Toast.makeText(getApplicationContext(), search, Toast.LENGTH_LONG).show();
}
});
}
public void get_data(String data){
try {
JSONObject jsonObj = new JSONObject(data);
JSONArray data_array = jsonObj.getJSONArray("announcements");
for (int i = 0 ; i < data_array.length() ; i++)
{
JSONObject obj=new JSONObject(data_array.get(i).toString());
Countries add=new Countries();
add.name = obj.getString("message");
add.code = obj.getString("date");
countries.add(add);
}
adapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
Download_data.java
public class Download_data implements Runnable {
public download_complete caller;
public interface download_complete{
public void get_data(String data);
}
Download_data(download_complete caller) {
this.caller = caller;
}
private String link;
public void download_data_from_link(String link){
this.link = link;
Thread t = new Thread(this);
t.start();
}
public void run() {
threadMsg(download(this.link));
}
private void threadMsg(String msg) {
if (!msg.equals(null) && !msg.equals("")) {
Message msgObj = handler.obtainMessage();
Bundle b = new Bundle();
b.putString("message", msg);
msgObj.setData(b);
handler.sendMessage(msgObj);
}
}
private final Handler handler = new Handler() {
public void handleMessage(Message msg) {
String Response = msg.getData().getString("message");
caller.get_data(Response);
}
};
public static String download(String url) {
URL website;
StringBuilder response = null;
try {
website = new URL(url);
HttpURLConnection connection = (HttpURLConnection) website.openConnection();
connection.setRequestProperty("charset", "utf-8");
BufferedReader in = new BufferedReader(
new InputStreamReader(
connection.getInputStream()));
response = new StringBuilder();
String inputLine;
while ((inputLine = in.readLine()) != null)
response.append(inputLine);
in.close();
} catch (Exception e) {
return "";
}
return response.toString();
}
ListAdapter.java
MainActivity main;
ListAdapter(MainActivity main)
{
this.main = main;
}
#Override
public int getCount() {
return main.countries.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
static class ViewHolderItem {
TextView name;
TextView code;
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
ViewHolderItem holder = new ViewHolderItem();
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) main.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.cell, null);
holder.name = (TextView) convertView.findViewById(R.id.name);
holder.code = (TextView) convertView.findViewById(R.id.code);
convertView.setTag(holder);
}
else
{
holder = (ViewHolderItem) convertView.getTag();
}
holder.name.setText(this.main.countries.get(position).name);
holder.code.setText(this.main.countries.get(position).code);
return convertView;
}
It appears that the countries list is being added to each time in get_data(), but never cleared out. At the start of get_data, you most likely want to clear the countries list with the following call:
countries.clear();
Then the data in the countries list will be cleared out, the new downloaded data will be added to the countries list, and then updated in the view when the adapter is notified of the data change.
I'm working on the Sunshine app in the Developing Android App course by Udacity. Currently stuck in lesson 2. I've listed down the MainActivity.java that contains a listview that is populated by a network call in the AsyncTask as an inner class in the MainActivity.java. But the application crashes, due to a null pointer exception, as the array adapter is null. I've tried debugging, and the weekForecast (i.e., the ArrayList that stores the parsed data, and is a parameter to the creation of the ArrayAdapter) does have valid parsed data. Thanks for the help in advance.
public class MainActivity extends AppCompatActivity {
ListView listView;
ArrayAdapter<String> arrayAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView=(ListView)findViewById(R.id.listview_forecast);
GettingWeatherFromNetwork gettingWeatherFromNetwork = new GettingWeatherFromNetwork();
gettingWeatherFromNetwork.execute("94043");
listView.setAdapter(arrayAdapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main,menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch(id) {
case R.id.action_settings : return true;
case R.id.action_refresh : GettingWeatherFromNetwork gettingWeatherFromNetwork = new GettingWeatherFromNetwork();
gettingWeatherFromNetwork.execute("94043");
return true;
}
return super.onOptionsItemSelected(item);
}
public class GettingWeatherFromNetwork extends AsyncTask<String, Void, String[]> {
private final String LOG_TAG = GettingWeatherFromNetwork.class.getSimpleName();
//Removed API KEY. But it is a part of the main code I'm running.
private final String API_KEY = " ";
#Override
protected String[] doInBackground(String... params) {
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
String forecastJsonStr = null;
String format = "json";
String units = "metric";
int noOfDays = 7;
try {
final String BASE_URL = "http://api.openweathermap.org/data/2.5/forecast/daily?";
final String QUERY_PARAM = "q";
final String MODE_PARAM = "mode";
final String UNITS_PARAM = "units";
final String COUNT_PARAM = "cnt";
final String KEY_PARAM = "appid";
Uri builtURI = Uri.parse(BASE_URL).buildUpon()
.appendQueryParameter(QUERY_PARAM,params[0])
.appendQueryParameter(MODE_PARAM,format)
.appendQueryParameter(UNITS_PARAM,units)
.appendQueryParameter(COUNT_PARAM, String.valueOf(noOfDays))
.appendQueryParameter(KEY_PARAM,API_KEY)
.build();
String Url = builtURI.toString();
URL url = new URL(Url);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
return null;
}
forecastJsonStr = buffer.toString();
} catch (IOException e) {
Log.e(LOG_TAG, String.valueOf(e));
return null;
} finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, String.valueOf(e));
}
}
}
String [] weatherForecast = new String[0];
WeatherParser weatherParser = new WeatherParser();
try {
weatherForecast = weatherParser.getWeatherDataFromJson(forecastJsonStr,7);
} catch (JSONException e) {
e.printStackTrace();
}
return weatherForecast;
}
#Override
protected void onPostExecute(String[] s) {
List<String> weekForecast = new ArrayList<String>(Arrays.asList(s));
arrayAdapter = new ArrayAdapter<String>(getApplicationContext(),R.layout.list_item_forecast,R.id.list_item_forecast_textview,weekForecast);
}
}
}
Try removing the line
listView.setAdapter(arrayAdapter);
from onCreate method and add it in onPostExecute() method of AsyncTask, after initialising the arrayAdapter.
#Override
protected void onPostExecute(String[] s) {
List<String> weekForecast = new ArrayList<String>(Arrays.asList(s));
arrayAdapter = new ArrayAdapter<String>(getApplicationContext(),R.layout.list_item_forecast,R.id.list_item_forecast_textview,weekForecast);
//set adapter set to listview after initialzing it.
listView.setAdapter(arrayAdapter);
}
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.
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.
so i have been at it for hours and its 4:07 AM now i have to sleep, so i hope someone can help me.
I have an ArrayList of ImageResults objects the class of which is defined as:
public class ImageResults {
String _title, _country, _thumbnailURL, _imageURL;
public ImageResults(String title, String country, String thumbnailURL, String imageURL)
{
_title = title;
_country = country;
_thumbnailURL = thumbnailURL;
_imageURL = imageURL;
}
public String getTitle()
{
return _title;
}
public String getCountry()
{
return _country;
}
public String getThumbnailURL()
{
return _thumbnailURL;
}
public String getImageURL()
{
return _imageURL;
}
}
Now in order to use https://github.com/thest1/LazyList i have to retrieve the thumbnail urls from my arraylist of type imageresults and place them in an array like im doing here
private void populateListBox()
{
String[] imgLst = new String[imagesList.size()];
for(int i = 0; i < imagesList.size();i++)
{
imgLst[i] = (imagesList.get(i)._thumbnailURL);
// Toast t = Toast.makeText(this,imgLst[0] , Toast.LENGTH_SHORT);
// t.show();
}
adapter=new LazyAdapter(this, imgLst);
imageListView.setAdapter(adapter);
}
now the thing is the way it is above is not working but if i take the link individually as follows it works which is the default way the links are organized in the original project
private void populateListBox()
{
String[] imgLst={
"http://www.istartedsomething.com/bingimages/resize.php?i=Velodrome_EN-AU1182456710.jpg&w=300"};
adapter=new LazyAdapter(this, imgLst);
imageListView.setAdapter(adapter);
}
this is how links are organized in the original project, and yest i am 100% sure that both methods are returning the same string just in different ways, one is fetching it from an object in an arraylist and the other im explicitly declaring it.
private String[] mStrings={
"http://www.istartedsomething.com/bingimages/resize.php?i=Velodrome_EN-AU1182456710.jpg&w=300",
"http://www.istartedsomething.com/bingimages/resize.php?i=Velodrome_EN-CA1182456710.jpg&w=300",
"http://a3.twimg.com/profile_images/121630227/Droid_normal.jpg",
"http://a1.twimg.com/profile_images/957149154/twitterhalf_normal.jpg",
"http://a1.twimg.com/profile_images/97470808/icon_normal.png",
"http://a3.twimg.com/profile_images/511790713/AG.png",
"http://a3.twimg.com/profile_images/956404323/androinica-avatar_normal.png",
"http://a1.twimg.com/profile_images/909231146/Android_Biz_Man_normal.png",
"http://a3.twimg.com/profile_images/72774055/AndroidHomme-LOGO_normal.jpg",
"http://a1.twimg.com/profile_images/349012784/android_logo_small_normal.jpg"};
main activity class
public class BngPaperActivity extends Activity {
ListView imageListView;
Spinner countrySpinner;
String selectedMonth;
String selectedYear;
LazyAdapter adapter;
ProgressDialog progress;
Dialog date;
getResult getRes;
String ResultsString;
ArrayList<String> monthList = new ArrayList<String>();
ArrayList<ImageResults> imagesList = new ArrayList<ImageResults>();
String dateText;
TextView selectedDateView;
static final int MONTHYEARDATESELECTOR_ID = 3;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
progress = new ProgressDialog(BngPaperActivity.this);
monthList.add("January"); monthList.add("February"); monthList.add("March"); monthList.add("April");
monthList.add("May"); monthList.add("June"); monthList.add("July"); monthList.add("August");
monthList.add("September"); monthList.add("October"); monthList.add("November"); monthList.add("December");
imageListView = (ListView) this.findViewById(R.id.imagesListView);
countrySpinner = (Spinner) this.findViewById(R.id.countrySpinner);
selectedDateView = (TextView) this.findViewById(R.id.selectedDateView);
Button monthYearButton = (Button) this.findViewById(R.id.monthyearBTN);
// set up a listener for when the button is pressed
monthYearButton.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
// call the internal showDialog method using the predefined ID
showDialog(MONTHYEARDATESELECTOR_ID);
}
});
}
private DateSlider.OnDateSetListener mMonthYearSetListener =
new DateSlider.OnDateSetListener() {
public void onDateSet(DateSlider view, Calendar selectedDate) {
// update the dateText view with the corresponding date
dateText = (String.format("%tB %tY", selectedDate, selectedDate));
selectedDateView.setText(dateText);
try {
selectedMonth = monthList.indexOf(String.format("%tB", selectedDate)) + 1 +"";
selectedYear = String.format("%tY", selectedDate);
progress.setMessage("Fetching Images... \nPress Back Button To Cancel");
progress.setCancelable(true);
getRes = new getResult(progress,view);
getRes.execute();
try {
ResultsString = getRes.get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
parseResults(ResultsString);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
private void parseResults(String result)
{
Scanner scan = new Scanner(result);
String current = scan.nextLine();
String title = "";
String country = "";
String thumbURL = "";
String imageURL = "";
while(!current.equals("End of file"))
{
if(current.equals("Begin Thumb"))
{
current = scan.nextLine();
title = current.substring(current.indexOf(":")+1);
current = scan.nextLine();
country = current.substring(current.indexOf(":")+1);
current = scan.nextLine();
thumbURL = current.substring(current.indexOf(":")+1);
imageURL = thumbURL.replace("300", "900");
current = scan.nextLine();
}
if(current.equals("End Thumb"))
{
imagesList.add(new ImageResults(title,country,thumbURL,imageURL));
}
current = scan.nextLine();
}
populateListBox();
}
private void populateListBox()
{
//this is not working, i would like this one to work
String[] imgLst = new String[imagesList.size()];
for(int i = 0; i < imagesList.size();i++)
{
imgLst[i] = (imagesList.get(i)._thumbnailURL);
// Toast t = Toast.makeText(this,imgLst[0] , Toast.LENGTH_SHORT);
// t.show();
}
//-----------------------------------
/* This is working
String[] imgLst={
"http://www.istartedsomething.com/bingimages/resize.php?i=Velodrome_EN-AU1182456710.jpg&w=300"};
*/
adapter=new LazyAdapter(this, imgLst);
imageListView.setAdapter(adapter);
}
#Override
protected Dialog onCreateDialog(int id) {
// this method is called after invoking 'showDialog' for the first time
// here we initiate the corresponding DateSlideSelector and return the dialog to its caller
final Calendar c = Calendar.getInstance();
final Calendar minDate = Calendar.getInstance();
minDate.set(Calendar.YEAR, 2009);
minDate.set(Calendar.MONTH, Calendar.JUNE);
final Calendar maxDate = Calendar.getInstance();
maxDate.add(Calendar.DATE, 0);
switch (id) {
case MONTHYEARDATESELECTOR_ID:
return new MonthYearDateSlider(this,mMonthYearSetListener,c,minDate,maxDate);
}
return null;
}
private class getResult extends AsyncTask<String, String, String> {
private final HttpClient Client = new DefaultHttpClient();
private String Content;
private String Error = null;
private ProgressDialog progress;
DateSlider view;
public getResult(ProgressDialog progress, DateSlider view)
{
this.progress = progress;
this.view = view;
}
protected void onPreExecute() {
this.view.dismiss();
this.progress.show();
}
#Override
protected String doInBackground(String... urls) {
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response;
String responseString = null;
try {
response = httpclient.execute(new HttpGet("http://devleb.com/BngPaper/BngPaperWebService.php?thumbnail=Yes&year="+selectedYear+"&month="+ selectedMonth));
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpStatus.SC_OK){
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
responseString = out.toString();
} else{
//Closes the connection.
response.getEntity().getContent().close();
throw new IOException(statusLine.getReasonPhrase());
}
} catch (ClientProtocolException e) {
//TODO Handle problems..
} catch (IOException e) {
//TODO Handle problems..
}
//Dialog.dismiss();
progress.dismiss();
return responseString;
}
protected void onPostExecute(Void unused) {
this.progress.dismiss();
if (Error != null) {
Toast.makeText(BngPaperActivity.this, Error, Toast.LENGTH_LONG).show();
}
}
}
}
The following doesn't work?
private void populateListBox()
{
adapter=new LazyAdapter(this, mStrings);
imageListView.setAdapter(adapter);
}
Like in the example given in the lazylist project.