List View not working fine on loading search data - android

I have implemented a Custom List View which displays text along with image. The List View fetches data from XML data present over the internet. When the user scrolls down, more data is loaded into the application. Now, I am trying to include a search bar so that when the user searches for some data, the application displays the results returned by the search. The main problem is that the list view doesn't show the correct data when search is performed.
When I check the URL that is being executed by the Search bar in a browser, it shows the correct results, but in Android application it behaves differently.
Below is the code of my Activity that performs this whole work:-
public class OrganizationActivity extends Activity implements OnScrollListener {
int itemsPerPage = 10;
boolean loadingMore = false;
int mPos=0;
// All static variables
static final String URL = "some URL";
static int page_no = 1;
// XML node keys
static final String KEY_ORGANIZATION = "organization"; // parent node
static final String KEY_ID = "id";
static final String KEY_NAME = "name";
static final String KEY_CITY = "city";
static final String KEY_STATE = "state";
static final String KEY_IMAGE_URL = "image";
ListView list;
LazyAdapter adapter;
ArrayList<HashMap<String, String>> orgsList = new ArrayList<HashMap<String, String>>();
private EditText filterText = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
filterText = (EditText) findViewById(R.id.search_box_et);
filterText.addTextChangedListener(new TextWatcher()
{
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
// TODO Auto-generated method stub
}
#Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
if(arg0.length()==0)
{
list.setAdapter(new LazyAdapter(OrganizationActivity.this, orgsList));
}
list.setAdapter(new LazyAdapter(OrganizationActivity.this, orgsList));
String searchtext = null;
try {
searchtext=URLEncoder.encode(arg0.toString().trim(),"UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String urlStr = "myURL?search="+searchtext;
new LoadData().execute(urlStr);
adapter = new LazyAdapter(OrganizationActivity.this, orgsList);
list.setAdapter(adapter);
}
});
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML from URL
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_ORGANIZATION);
// looping through all organization nodes <organization>
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_ID, parser.getValue(e, KEY_ID));
map.put(KEY_NAME, parser.getValue(e, KEY_NAME));
map.put(KEY_CITY, parser.getValue(e, KEY_CITY));
map.put(KEY_STATE, parser.getValue(e, KEY_STATE));
map.put(KEY_IMAGE_URL, parser.getValue(e, KEY_IMAGE_URL));
// adding HashList to ArrayList
orgsList.add(map);
}
list = (ListView) findViewById(R.id.list);
View footerView = ((LayoutInflater) this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
R.layout.listfooter, null, false);
list.addFooterView(footerView);
// Getting adapter by passing xml data ArrayList
adapter = new LazyAdapter(this, orgsList);
list.setAdapter(adapter);
list.setOnScrollListener(this);
// Click event for single list row
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String name = orgsList.get(position).get(KEY_NAME).toString();
Toast.makeText(getApplicationContext(), name, Toast.LENGTH_LONG)
.show();
}
});
}
private class LoadData extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
for (String url : urls) {
// TODO Auto-generated method stub
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(url); // getting XML from URL
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_ORGANIZATION);
// looping through all organization nodes <organization>
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_ID, parser.getValue(e, KEY_ID));
map.put(KEY_NAME, parser.getValue(e, KEY_NAME));
map.put(KEY_CITY, parser.getValue(e, KEY_CITY));
map.put(KEY_STATE, parser.getValue(e, KEY_STATE));
map.put(KEY_IMAGE_URL, parser.getValue(e, KEY_IMAGE_URL));
// adding HashList to ArrayList
orgsList.add(map);
}
}
return null;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
adapter = new LazyAdapter(OrganizationActivity.this, orgsList);
list.setAdapter(adapter);
list.setSelectionFromTop(mPos, 0);
}
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
//Get the visible item position
mPos=list.getFirstVisiblePosition();
int lastInScreen = firstVisibleItem + visibleItemCount;
//Is the bottom item visible & not loading more already? Load more !
if ((lastInScreen == totalItemCount) && !(loadingMore)) {
page_no++;
String pageURL = "myURL?page="
+ page_no;
new LoadData().execute(pageURL);
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
}
}
Please help me out in finding the solution to this problem...

Looks like I was doing little bit of mistake in refreshing my ListView with the new data and also I was calling the notifyDataSetListener somewhere else. Now it is working absolutely fine..

Related

Handle Scrolling Android

I have used json with my Listview in fragment but it take time because i have 190 object so i want it to show only 15 items of Json and will so 15 more if the user scroll to the end. My json file i got from dropbox the size is 2,3MB. Can any tell me a good suggestion ? Thank in advance.
Here are the code.
public class UniversityFragment extends Fragment implements OnScrollListener{
ListView lv;
private ProgressDialog pDialog;
// JSON Node names
private static final String TAG_CONTACTS = "contacts";
private static final String TAG_NAME = "name";
private static final String TAG_ADDRESS = "address";
private static final String TAG_CityProvince = "city/province";
private static final String TAG_Country = "country";
private static final String TAG_PHONE_OFFICE = "officephone";
private static final String TAG_Fax = "fax";
private static final String TAG_EMAIL = "email";
private static final String TAG_Site = "site";
private static final String TAG_image = "image";
int textlength = 0;
// contacts JSONArray
JSONArray contacts = null;
JSONObject jsonobject;
// Hashmap for ListView
ArrayList<HashMap<String, String>> contactList;
// Search EditText
EditText inputSearch;
public UniversityFragment() {
}
#SuppressLint("CutPasteId")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_university,
container, false);
// Execute DownloadJSON AsyncTask
contactList = new ArrayList<HashMap<String, String>>();
lv = (ListView) rootView.findViewById(R.id.listView1);
inputSearch = (EditText) rootView.findViewById(R.id.inputSearch);
lv.setTextFilterEnabled(true);
inputSearch.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int start, int before,
int count) {
// TODO Auto-generated method stub
// When user changed the Text
// UniversityFragment.this.adapter.getFilter().filter(cs);
}
#Override
public void beforeTextChanged(CharSequence cs, int start,
int count, int after) {
// TODO Auto-generated method stub
try {
// ((Filterable)
// UniversityFragment.this.contacts).getFilter().filter(cs);
} catch (Exception e) {
// TODO: handle exception
Toast.makeText(getActivity(), "" + e, Toast.LENGTH_SHORT)
.show();
}
// lv.setTextFilterEnabled(true);
}
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});
// Listview on item click listener
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// TODO Auto-generated method stub
Toast.makeText(getActivity(), "Clicked" + position,
Toast.LENGTH_LONG).show();
// getting values from selected ListItem
String name = ((TextView) view.findViewById(R.id.name))
.getText().toString();
String cp = ((TextView) view.findViewById(R.id.CPt)).getText()
.toString();
String country = ((TextView) view.findViewById(R.id.countryt))
.getText().toString();
String fax = ((TextView) view.findViewById(R.id.faxt))
.getText().toString();
String site = ((TextView) view.findViewById(R.id.sitet))
.getText().toString();
String email = ((TextView) view.findViewById(R.id.emailt))
.getText().toString();
String phone = ((TextView) view.findViewById(R.id.phonet))
.getText().toString();
String address = ((TextView) view.findViewById(R.id.addresst))
.getText().toString();
// Starting single contact activity
Intent in = new Intent(getActivity(), SingleListItem.class);
in.putExtra("email", email);
in.putExtra("city/province", cp);
in.putExtra("country", country);
in.putExtra("fax", fax);
in.putExtra("site", site);
in.putExtra("name", name);
in.putExtra("officephone", phone);
in.putExtra("address", address);enter code here
startActivity(in);
}
});
lv.setOnScrollListener(new OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
if (firstVisibleItem+visibleItemCount == totalItemCount && totalItemCount!=0) {
}
}
});
// Calling async task to get json
new GetContacts().execute();
return rootView;
}
/**
* Async task class to get json by making HTTP call
* */
private class GetContacts extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Showing progress dialog
pDialog = new ProgressDialog(getActivity());
pDialog.setTitle("Loading");
pDialog.setMessage("Please wait...");
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
// Create an array
contactList = new ArrayList<HashMap<String, String>>();
// Retrieve JSON Objects from the given URL address
// Creating service handler class instance
ServiceHandler sh = new ServiceHandler();
String url = "https://dl.dropbox.com........";
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url, ServiceHandler.GET);
enter code here
// Log.d("Response: ", "> " + jsonStr);
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
// Getting JSON Array node
contacts = jsonObj.getJSONArray(TAG_CONTACTS);
// looping through All Contacts
for (int i = 0; i < contacts.length(); i++) {
JSONObject c = contacts.getJSONObject(i);
String name = c.getString(TAG_NAME);
String address = c.getString(TAG_ADDRESS);
String country = c.getString(TAG_Country);
String cityprovince = c.getString(TAG_CityProvince);
String officephone = c.getString(TAG_PHONE_OFFICE);
String fax = c.getString(TAG_Fax);
String email = c.getString(TAG_EMAIL);
String site = c.getString(TAG_Site);
// // Phone node is JSON Object
// JSONObject phone = c.getJSONObject(TAG_PHONE);
// String home = phone.getString(TAG_PHONE_HOME);
// tmp hashmap for single contact
HashMap<String, String> contact = new HashMap<String, String>();
// adding each child node to HashMap key => value
contact.put(TAG_NAME, name);
contact.put(TAG_ADDRESS, address);
contact.put(TAG_CityProvince, cityprovince);
contact.put(TAG_Country, country);
contact.put(TAG_PHONE_OFFICE, officephone);
contact.put(TAG_EMAIL, email);
contact.put(TAG_Site, site);
contact.put(TAG_Fax, fax);
// adding contact to contact list
contactList.add(contact);
}
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Log.e("ServiceHandler", "Couldn't get any data from the url");
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
Toast.makeText(getActivity(), "Thank for your patience", Toast.LENGTH_LONG).show();
/**
* Updating parsed JSON data into ListView
* */
ListAdapter adapter = new SimpleAdapter(getActivity(), contactList,
R.layout.listsingleitem, new String[] { TAG_NAME,
TAG_ADDRESS, TAG_CityProvince, TAG_Country,
TAG_PHONE_OFFICE, TAG_Fax, TAG_EMAIL, TAG_Site },
new int[] { R.id.name, R.id.addresst, R.id.CPt,
R.id.countryt, R.id.phonet, R.id.faxt, R.id.emailt,
R.id.sitet });
adapter.notify();
//adapter.notifyDataSetChanged();
lv.setAdapter(adapter);
}
}
You need to implement an endless adapter (custom listview adapter) to support loading and displaying concurrently.
See this tutorial: http://www.survivingwithandroid.com/2013/10/android-listview-endless-adapter.html

Android ListView reload data

Is it possible to reload a ListView once the data is downloaded? Basically I'm updating an app for 4.1 but my ListView downloads and parses an XML file, I know that I have to run this now in a background thread but when I open the activity via a tab the screen is blank. I am not sure how to get this to work or what part of the code I need to use in the background thread, can someone please help. Thank you.
public class ThirdActivity extends ListActivity {
// All static variables
static final String URL = "http://selectukradio.com/SelectUKSchedule.xml"; // http://api.androidhive.info/pizza/?format=xml http://selectukradio.com/SelectUKSchedule.xml
// XML node keys
static final String KEY_ITEM = "day"; // parent node item
static final String KEY_ID = "link"; // id
static final String KEY_NAME = "dj"; // name
static final String KEY_COST = "time"; // cost
static final String KEY_DESC = "tempDay"; // description
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_3);
try{
ArrayList<HashMap<String, String>> menuItems = new ArrayList<HashMap<String, String>>();
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_ITEM);
// looping through all item nodes <item>
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_ID, parser.getValue(e, KEY_ID));
map.put(KEY_NAME, parser.getValue(e, KEY_NAME));
map.put(KEY_COST, parser.getValue(e, KEY_COST)); // "Rs. " +
map.put(KEY_DESC, parser.getValue(e, KEY_DESC));
// adding HashList to ArrayList
menuItems.add(map);
}
// Adding menuItems to ListView
ListAdapter adapter = new SimpleAdapter(ThirdActivity.this, menuItems,
R.layout.list_item,
new String[] { KEY_NAME, KEY_COST,KEY_DESC,KEY_ID }, new int[] {
R.id.name, R.id.cost, R.id.day, R.id.link });
setListAdapter(adapter);
// selecting single ListView item
ListView lv = getListView();
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// getting values from selected ListItem
String name = ((TextView) view.findViewById(R.id.name)).getText().toString();
String cost = ((TextView) view.findViewById(R.id.cost)).getText().toString();
String link = ((TextView) view.findViewById(R.id.link)).getText().toString();
// Starting new intent
Intent in = new Intent(getApplicationContext(), SingleMenuItemActivity.class);
in.putExtra(KEY_NAME, name);
in.putExtra(KEY_COST, cost);
in.putExtra(KEY_ID, link);
startActivity(in);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
#Override public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
startActivity(intent);
}
return super.onKeyDown(keyCode, event);
}
}
Nick's comment has upvotes but everyone is forgetting that notifyDataSetChanged() must be called on the adapter, not on the list view.
In this example you are using a SimpleAdapter which takes the list of items in the constructor. So to change the data wrapped by the adapter, you have to update this list and then call notifyDataSetChanged() on the adapter to get the list view to update.
Here's how you could rework the code to solve your problems. All I have done is move the XML download code to an AsyncTask, and moved the list adapter and data items to be instance variables so you can access them when async task completes.
Please note I haven't tested this code, but it should give you the right idea!
public class ThirdActivity extends ListActivity {
// All static variables
static final String URL = "http://selectukradio.com/SelectUKSchedule.xml"; // http://api.androidhive.info/pizza/?format=xml http://selectukradio.com/SelectUKSchedule.xml
// XML node keys
static final String KEY_ITEM = "day"; // parent node item
static final String KEY_ID = "link"; // id
static final String KEY_NAME = "dj"; // name
static final String KEY_COST = "time"; // cost
static final String KEY_DESC = "tempDay"; // description
// Initially set list of items to empty array
ArrayList<HashMap<String, String>> mMenuItems = new ArrayList<HashMap<String, String>>();
SimpleAdapter mAdapter;
UpdateTask mUpdateTask;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_3);
// Adding menuItems to ListView
mAdapter = new SimpleAdapter(ThirdActivity.this, mMenuItems,
R.layout.list_item,
new String[] { KEY_NAME, KEY_COST,KEY_DESC,KEY_ID },
new int[] { R.id.name, R.id.cost, R.id.day, R.id.link });
setListAdapter(mAdapter);
// selecting single ListView item
ListView lv = getListView();
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// getting values from selected ListItem
String name = ((TextView) view.findViewById(R.id.name)).getText().toString();
String cost = ((TextView) view.findViewById(R.id.cost)).getText().toString();
String link = ((TextView) view.findViewById(R.id.link)).getText().toString();
// Starting new intent
Intent in = new Intent(getApplicationContext(), SingleMenuItemActivity.class);
in.putExtra(KEY_NAME, name);
in.putExtra(KEY_COST, cost);
in.putExtra(KEY_ID, link);
startActivity(in);
}
});
// Start an update
updateMenuItems();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
startActivity(intent);
return true; // handled event
}
return super.onKeyDown(keyCode, event);
}
// Call this method to download latest XML file from network and update listview
private void updateMenuItems() {
if (mUpdateTask == null) {
mUpdateTask = new UpdateTask();
mUpdateTask.execute(URL);
}
}
// Async task to download XML on background thread
private class UpdateTask extends AsyncTask<String, Void, String> {
// This method runs on a background.
// Do network operation and returns XML parser, or null on exception
protected String doInBackground(String... url) {
try {
XMLParser parser = new XMLParser();
return parser.getXmlFromUrl(url[0]);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
// This method runs on the main thread when the async task completes.
// Make sure you only update your UI from this method!
protected void onPostExecute(String xml) {
if (xml == null) {
// Download failed, display error message or something
return;
}
XMLParser parser = new XMLParser();
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_ITEM);
// looping through all item nodes <item>
mMenuItems.clear();
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_ID, parser.getValue(e, KEY_ID));
map.put(KEY_NAME, parser.getValue(e, KEY_NAME));
map.put(KEY_COST, parser.getValue(e, KEY_COST)); // "Rs. " +
map.put(KEY_DESC, parser.getValue(e, KEY_DESC));
// adding HashList to ArrayList
mMenuItems.add(map);
}
// all done, notify listview adapter to update
mAdapter.notifyDataSetChanged();
}
}
}
Here is the final class
public class ThirdActivity extends ListActivity {
// All static variables
static final String URL = "http://selectukradio.com/SelectUKSchedule.xml"; // http://api.androidhive.info/pizza/?format=xml http://selectukradio.com/SelectUKSchedule.xml
// XML node keys
static final String KEY_ITEM = "day"; // parent node item
static final String KEY_ID = "link"; // id
static final String KEY_NAME = "dj"; // name
static final String KEY_COST = "time"; // cost
static final String KEY_DESC = "tempDay"; // description
String xml = new String();
// Initially set list of items to empty array
ArrayList<HashMap<String, String>> mMenuItems = new ArrayList<HashMap<String, String>>();
SimpleAdapter mAdapter;
UpdateTask mUpdateTask;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_3);
// Adding menuItems to ListView
mAdapter = new SimpleAdapter(ThirdActivity.this, mMenuItems,
R.layout.list_item,
new String[] { KEY_NAME, KEY_COST,KEY_DESC,KEY_ID },
new int[] { R.id.name, R.id.cost, R.id.day, R.id.link });
setListAdapter(mAdapter);
// selecting single ListView item
ListView lv = getListView();
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// getting values from selected ListItem
String name = ((TextView) view.findViewById(R.id.name)).getText().toString();
String cost = ((TextView) view.findViewById(R.id.cost)).getText().toString();
String link = ((TextView) view.findViewById(R.id.link)).getText().toString();
// Starting new intent
Intent in = new Intent(getApplicationContext(), SingleMenuItemActivity.class);
in.putExtra(KEY_NAME, name);
in.putExtra(KEY_COST, cost);
in.putExtra(KEY_ID, link);
startActivity(in);
}
});
// Start an update
updateMenuItems();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
startActivity(intent);
return true; // handled event
}
return super.onKeyDown(keyCode, event);
}
// Call this method to download latest XML file from network and update listview
private void updateMenuItems() {
if (mUpdateTask == null) {
mUpdateTask = new UpdateTask();
mUpdateTask.execute(URL);
}
}
// Async task to download XML on background thread
private class UpdateTask extends AsyncTask<String, Void, XMLParser> {
// This method runs on a background.
// Do network operation and returns XML parser, or null on exception
protected XMLParser doInBackground(String... url) {
try {
XMLParser parser = new XMLParser();
xml = parser.getXmlFromUrl(url[0]);
// xml = parser.getXmlFromUrl(URL); // getting XML
return parser;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
// This method runs on the main thread when the async task completes.
// Make sure you only update your UI from this method!
protected void onPostExecute(XMLParser parser) {
if (parser == null) {
// Download failed, display error message or something
return;
}
// String xml = parser.getXmlFromUrl(URL); // getting XML
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_ITEM);
// looping through all item nodes <item>
mMenuItems.clear();
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_ID, parser.getValue(e, KEY_ID));
map.put(KEY_NAME, parser.getValue(e, KEY_NAME));
map.put(KEY_COST, parser.getValue(e, KEY_COST)); // "Rs. " +
map.put(KEY_DESC, parser.getValue(e, KEY_DESC));
// adding HashList to ArrayList
mMenuItems.add(map);
}
// all done, notify listview adapter to update
mAdapter.notifyDataSetChanged();
}
}
}

Progress Dialog is shown only for a very little time in Async Task and the activity loading is slow

I'm developing my first Android application and i want to show a progress dialog until a xml file is being processed in doInBackground method. This activity is loaded in response to an onclick event. Unexpectedly, activity takes several seconds to show up and the progress dialog is shown for a very little time (several milliseconds).
This is my code. I have used AsyncTask as an inner class. I just can't find where i have gone wrong.
public class WhatToSee extends ListActivity {
ListView whatToSee;
ArrayList<HashMap<String, String>> whatToSeeInfo = new ArrayList<HashMap<String, String>>();
WhatToSeeAdapter adapter;
String cityName;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.whattosee);
cityName = getIntent().getStringExtra("name");
whatToSee = (ListView) findViewById(android.R.id.list);
adapter= new WhatToSeeAdapter(this, whatToSeeInfo);
whatToSee.setAdapter(adapter);
new WhatToSeeLoader().execute();
}
public class WhatToSeeLoader extends AsyncTask<Void, String, String> {
ProgressDialog progress = new ProgressDialog(WhatToSee.this);
String url = "http://wearedesigners.net/clients/clients12/tourism/fetchWhatToSeeList.php";
final String TAG_MAIN = "item";
final String TAG_ID = "itemId";
final String TAG_NAME = "itemName";
final String TAG_DETAIL = "itemDetailText";
final String TAG_MAP = "itemMapData";
final String TAG_ITEM_IMAGE = "itemImages";
final String TAG_MAP_IMAGE = "mapImage";
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(url); // getting XML
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(TAG_MAIN);
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
progress.setMessage("Loading What To See List");
progress.setIndeterminate(true);
progress.show();
}
#Override
protected String doInBackground(Void... params) {
// TODO Auto-generated method stub
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(TAG_ID, parser.getValue(e, TAG_ID));
map.put(TAG_NAME, parser.getValue(e, TAG_NAME));
map.put(TAG_DETAIL, parser.getValue(e, TAG_DETAIL));
map.put(TAG_MAP, parser.getValue(e, TAG_MAP));
map.put(TAG_MAP_IMAGE, parser.getValue(e, TAG_MAP_IMAGE));
map.put(TAG_ITEM_IMAGE, parser.getValue(e, TAG_ITEM_IMAGE));
// adding HashList to ArrayList
whatToSeeInfo.add(map);
}
return null;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
adapter.notifyDataSetChanged();
progress.dismiss();
}
}
}
Can someone please help me with this?
Thank you in advance.
Most probably call String xml = parser.getXmlFromUrl(url); // getting XML slows down Your code. It get executed in main thread and I expect it (from its name) to do some network related staff which basically should be done not in UI thread (e.g. in Yours doInBackground method).
So, to fix try to move that initialization staff related to xml inside doInBackground().

Use progress Dialog in footer

I am making an app in which I have to add progress dialog in footer View but I am unable to get any progress dialog in footer view:
Main Activity:
I want to add progress dialog in footer in this class
public class MainActivity extends Activity implements OnScrollListener {
// All variables
XmlParser parser;
Document doc;
String xml;
ListView lv;
ListViewAdapter adapter;
ArrayList<HashMap<String, String>> menuItems;
ProgressDialog pDialog;
private String URL = "http://api.androidhive.info/list_paging/?page=1";
// XML node keys
static final String KEY_ITEM = "item"; // parent node
static final String KEY_ID = "id";
static final String KEY_NAME = "name";
ProgressDialog dialog;
// Flag for current page
int current_page = 1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lv = (ListView) findViewById(R.id.list);
menuItems = new ArrayList<HashMap<String, String>>();
parser = new XmlParser();
xml = parser.getXmlFromUrl(URL); // getting XML
doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_ITEM);
// looping through all item nodes <item>
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_ID, parser.getValue(e, KEY_ID)); // id not using any where
map.put(KEY_NAME, parser.getValue(e, KEY_NAME));
// adding HashList to ArrayList
menuItems.add(map);
}
// LoadMore button
dialog=new ProgressDialog(this);
// Button btnLoadMore = new Button(this);
//btnLoadMore.setText("Load More");
// Adding Load More button to lisview at bottom
// lv.addFooterView(dialog);
// I want to use Progress Dialog in footer
/* lv.addFooterView(dialog);*/
// Getting adapter
adapter = new ListViewAdapter(this, menuItems);
lv.setAdapter(adapter);
lv.setOnScrollListener(this);
lv.addFooterView(dialog.getListView());
/**
* Listening to Load More button click event
* */
if(dialog.isShowing())
{
}
/* btnLoadMore.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
// Starting a new async task
new loadMoreListView().execute();
}
});*/
/**
* Listening to listview single row selected
* **/
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// getting values from selected ListItem
String name = ((TextView) view.findViewById(R.id.name))
.getText().toString();
// Starting new intent
Intent in = new Intent(getApplicationContext(),
Test123.class);
in.putExtra(KEY_NAME, name);
startActivity(in);
}
});
}
/**
* Async Task that send a request to url
* Gets new list view data
* Appends to list view
* */
private class loadMoreListView extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
// Showing progress dialog before sending http request
if(dialog.isShowing())
{
dialog.cancel();
}
else
{
pDialog = new ProgressDialog(
MainActivity.this);
pDialog.setMessage("Please wait..");
pDialog.setIndeterminate(true);
pDialog.setCancelable(false);
pDialog.show();
}
}
protected Void doInBackground(Void... unused) {
runOnUiThread(new Runnable() {
public void run() {
// increment current page
current_page += 1;
// Next page request
URL = "http://api.androidhive.info/list_paging/?page=" + current_page;
xml = parser.getXmlFromUrl(URL); // getting XML
doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_ITEM);
// looping through all item nodes <item>
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_ID, parser.getValue(e, KEY_ID));
map.put(KEY_NAME, parser.getValue(e, KEY_NAME));
// adding HashList to ArrayList
menuItems.add(map);
}
// get listview current position - used to maintain scroll position
int currentPosition = lv.getFirstVisiblePosition();
// Appending new data to menuItems ArrayList
adapter = new ListViewAdapter(
MainActivity.this,
menuItems);
lv.setAdapter(adapter);
// Setting new scroll position
lv.setSelectionFromTop(currentPosition + 1, 0);
}
});
return (null);
}
protected void onPostExecute(Void unused) {
// closing progress dialog
pDialog.dismiss();
}
}
public void onScroll(AbsListView arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
dialog.show();
lv.setOnScrollListener(this);
lv.addFooterView(dialog.getListView());
new loadMoreListView().execute();
}
public void onScrollStateChanged(AbsListView arg0, int arg1) {
// TODO Auto-generated method stub
new loadMoreListView().execute();
}
}
Adapter:
public class ListViewAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater=null;
public ListViewAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
data=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.list_item, null);
TextView name = (TextView)vi.findViewById(R.id.name);
HashMap<String, String> item = new HashMap<String, String>();
item = data.get(position);
//Setting all values in listview
name.setText(item.get("name"));
return vi;
}
}
XmlParser
public class XmlParser {
// constructor
public XmlParser() {
}
public 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;
}
/**
* Getting XML DOM element
* #param XML string
* */
public Document getDomElement(String xml){
Document doc = null;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xml));
doc = db.parse(is);
} catch (ParserConfigurationException e) {
Log.e("Error: ", e.getMessage());
return null;
} catch (SAXException e) {
Log.e("Error: ", e.getMessage());
return null;
} catch (IOException e) {
Log.e("Error: ", e.getMessage());
return null;
}
return doc;
}
/** Getting node value
* #param elem element
*/
public final String getElementValue( Node elem ) {
Node child;
if( elem != null){
if (elem.hasChildNodes()){
for( child = elem.getFirstChild(); child != null; child = child.getNextSibling() ){
if( child.getNodeType() == Node.TEXT_NODE ){
return child.getNodeValue();
}
}
}
}
return "";
}
/**
* Getting node value
* #param Element node
* #param key string
* */
public String getValue(Element item, String str) {
NodeList n = item.getElementsByTagName(str);
return this.getElementValue(n.item(0));
}
}
Any help will be appreciated.
I think, You want a ProgressBar and not ProgressDialog
Add a new layout pb_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ProgressBar
android:id="#+id/progressBar1"
style="?android:attr/progressBarStyleSmall"
android:indeterminate="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
In code add
view = getLayoutInflater().inflate(R.layout.pb_layout, null);
TextView tv = (TextView)view.findViewById(R.id.textView1);
tv.setText("Please wait..");
ProgressBar pb = (ProgressBar)view.findViewById(R.id.progressBar1);
pb.setIndeterminate(true);
lv.addFooterView(view);
You can only do addFooterView before you do setadapter.
You can write a simple/enhanced custom control with special actions and behaviors. For example a complete menu system on this thread
https://stackoverflow.com/a/11805044/1290995
An enhanced layout is very simpler than the menu in above link.
Some points to make a progressDialog like window:
Use FrameLayout as root view
Design it in an XML Layout file
Inflate it in a subclass of FrameLayout ( in Constructor )
Provide some method like show() , hide(), stop() or everything else you need and implements those actions
Pass a layout to the custom control to use as it's parent like
public void addTo(ViewGroup viewgroup){
viewgroup.addView(this);
}
and more...
If you need more information let me know.
You can Try this:
ProgressDialog myDialog = ProgressDialog.show(MyActivity.this, "Display Information","atthe bottom...", true);
myDialog.getWindow().setGravity(Gravity.BOTTOM);

How to retrieve value from ArrayList in android

I am trying to retrieve values from a json api and displaying then in a listView. The listView contains 3 elements and I am also implementing onItemClickListner() and when an Item is clicked it will display a detailed view related to that item. I am using an ArrayList to store all the json values. Now I want to retrieve a value from that ArrayList so that the OnClickListner() will get that value and from that value the detailed view will be displayed..
I am using AsyncTask to retrieve all the json values
#Override
protected String doInBackground(String... DATA) {
if(rqst_type.equals("top5"))
{
String url = DATA[1];
JsonParser jParser = new JsonParser();
JSONObject json = jParser.getJSONfromUrl(url);
try
{
JSONArray top5 = json.getJSONArray(TAG_TOP5);
public static ArrayList<HashMap<String, String>> top5List = new ArrayList<HashMap<String, String>>();
top5List.clear();
for(int i=0; i<top5.length(); i++)
{
Log.v(TAG_LOG, "Value of i: "+String.valueOf(i));
JSONObject t = top5.getJSONObject(i);
course_id = t.getString(TAG_CRSID);
created_date = t.getString(TAG_CRTDATE);
golfcourse_name = t.getString(TAG_GLFCRSNAME);
facilities = t.getString(TAG_FCLTY);
holes = t.getString(TAG_HOLES);
HashMap<String, String> map = new HashMap<String, String>();
map.put(TAG_CRSID, course_id);
map.put(TAG_CRTDATE, created_date);
map.put(TAG_GLFCRSNAME, golfcourse_name);
map.put(TAG_FCLTY, facilities);
map.put(TAG_HOLES, holes);
top5List.add(map);
Log.v(LoadingScreen.TAG_LOG, "top5List: "+String.valueOf(top5List));
}
}
catch(JSONException e)
{
Log.v(TAG_LOG, String.valueOf(e));
}
}
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
if(rqst_type.equals("top5"))
{
Intent in = new Intent(context, MyTop5.class);
in.putExtra(TAG_CRSID, course_id);
in.putExtra(TAG_CRTDATE, created_date);
in.putExtra(TAG_GLFCRSNAME, golfcourse_name);
in.putExtra(TAG_FCLTY, facilities);
in.putExtra(TAG_HOLES, holes);
Log.v(TAG_LOG, "Valuse to MyTop5: "+course_id+" "+created_date+" "+golfcourse_name+" "+
facilities+" "+holes);
context.startActivity(in);
}
This is the file to where I am displaying the list and the onItenClickListner()..
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.my_top5);
Intent in = getIntent();
golfcourse_name = in.getStringExtra(TAG_GLFCRSNAME);
course_id = in.getStringExtra(TAG_CRSID);
created_date = in.getStringExtra(TAG_CRTDATE);
facilities = in.getStringExtra(TAG_FCLTY);
holes = in.getStringExtra(TAG_HOLES);
Log.v(LoadingScreen.TAG_LOG, "course id: "+String.valueOf(course_id));
ListAdapter adapter = new SimpleAdapter(this, LoadingScreen.top5List, R.layout.top5_list,
new String[] { TAG_GLFCRSNAME, TAG_CRSID, TAG_CRTDATE, TAG_FCLTY, TAG_HOLES },
new int[] { R.id.top_golfname, R.id.top_courseid, R.id.top_createdate, R.id.top_fclty, R.id.top_holes });
setListAdapter(adapter);
Log.v(LoadingScreen.TAG_LOG, "course id: "+String.valueOf(course_id));
ListView lv = getListView();
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
String url = "http://mygogolfteetime.com/iphone/viewdeal/127";
new LoadingScreen(MyTop5.this).execute("view_detail", url);
}
});
}
In the given URL I want to change the 127 to the value which is stored in the top5List.
String url = "http://mygogolfteetime.com/iphone/viewdeal/127";
The value I am trying to find in the top5List is the value of "course_id"
Thanks in advance..
top5List.get(your position).get(your Key);
With this code you can find the value on which you want to change.

Categories

Resources