SAX Parsing doesn't fill ListView - android

I'm sorry for my bad english firstly.
Here is my goal;
I need to read xml (actually from web service but there are some problem with my host and i use direct xml link, as my web services return data) from my link. Then i need to write those data to listView.
And here is my problem;
I read that xml from web link and i think parsed xml. I say like this because when i debug project i can see some data on my GettersSetters variable. But when i send those data to my adapter class, there is no action, i guess. Because i can not see any changes on my listView.
Here is my MainActivity.java
public class MainActivity extends Activity {
XMLGettersSetters data;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
SAXParserFactory saxPF = SAXParserFactory.newInstance();
SAXParser saxP = saxPF.newSAXParser();
XMLReader xmlR = saxP.getXMLReader();
URL url = new URL("http://utkuyegen.com/dersProgramiListele.xml");
XMLHandler myXMLHandler = new XMLHandler();
xmlR.setContentHandler(myXMLHandler);
xmlR.parse(new InputSource(url.openStream()));
} catch (Exception e) {
Log.e("xmlParser", e.getMessage());
System.out.println(e);
}
data = XMLHandler.data;
System.out.println("data = XMLHandler.data");
try {
ListView lv = (ListView) findViewById(R.id.listView1);
System.out.println("listView tanımlandı");
dataAdapter adapter = new dataAdapter(this, R.layout.listview_row,
data.getDersID(), data.getDersAdi());
System.out.println("adapter tanımlandı");
lv.setAdapter(adapter);
System.out.println("adapter listView 'e atandı");
// TextView textView1 = (TextView) findViewById(R.id.textView1);
// textView1.setText(data.getDersID().get(2));
System.out.println("onCreate son satır");
} catch (Exception e) {
Log.d("tag", e.getMessage());
}
}
public class dataAdapter extends ArrayAdapter<XMLGettersSetters> {
// XMLGettersSetters items;
ArrayList<String> _dID, _dAdi;
public dataAdapter(Context context, int textViewResourceId,
ArrayList<String> dID, ArrayList<String> dAdi) {
super(context, textViewResourceId);
this._dID = dID;
this._dAdi = dAdi;
Log.d("da", "1");
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.listview_row, null);
Log.d("da", "5");
}
Log.d("da", "2");
TextView dersID = (TextView) convertView.findViewById(R.id.dersID);
TextView dersAdi = (TextView) convertView
.findViewById(R.id.dersAdi);
Log.d("da", "3");
dersID.setText(_dID.get(position));
dersAdi.setText(_dAdi.get(position));
Log.d("da", "4");
return convertView;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
And XMLGettersSetters.java
public class XMLGettersSetters {
private ArrayList<String> dersID = new ArrayList<String>();
private ArrayList<String> dersAdi = new ArrayList<String>();
public XMLGettersSetters(ArrayList<String> dersID, ArrayList<String> dersAdi) {
this.dersID = dersID;
this.dersAdi = dersAdi;
}
public XMLGettersSetters() {
}
public String getDersID_tek(int i) {
return dersID.get(i);
}
public ArrayList<String> getDersID() {
return dersID;
}
public void setDersID(String dersID) {
this.dersID.add(dersID);
}
public String getDersAdi_tek(int i) {
return dersAdi.get(i);
}
public ArrayList<String> getDersAdi() {
return dersAdi;
}
public void setDersAdi(String dersAdi) {
this.dersAdi.add(dersAdi);
}
}
And XMLHandler.java
public class XMLHandler extends DefaultHandler {
String elementValue = null;
Boolean elementOn = false;
public static XMLGettersSetters data = null;
public static XMLGettersSetters getXMLData() {
return data;
}
public static void setXMLData(XMLGettersSetters data) {
XMLHandler.data = data;
}
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
elementOn = true;
if (localName.equals("ArrayOfDersProgrami"))
{
data = new XMLGettersSetters();
} else if (localName.equals("dersProgrami"))
{
/**
* We can get the values of attributes for eg. if the CD tag had an attribute( <CD attr= "band">Akon</CD> )
* we can get the value "band". Below is an example of how to achieve this.
*
* String attributeValue = attributes.getValue("attr");
* data.setAttribute(attributeValue);
*
* */
}
}
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
elementOn = false;
/**
* Sets the values after retrieving the values from the XML tags
* */
if (localName.equalsIgnoreCase("DersID"))
data.setDersID(elementValue);
if (localName.equalsIgnoreCase("DersAdi"))
data.setDersAdi(elementValue);
}
#Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if (elementOn) {
elementValue = new String(ch, start, length);
elementOn = false;
}
}
}
BTW, i got some point with my code and debug.
When i debug this codes, i see that i can not understand data.
This is my xml file
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfDersProgrami xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
<dersProgrami>
<DersID>0</DersID>
<DersAdi>0</DersAdi>
</dersProgrami>
<dersProgrami>
<DersID>1</DersID>
<DersAdi>1</DersAdi>
</dersProgrami>
<dersProgrami>
<DersID>2</DersID>
<DersAdi>4</DersAdi>
</dersProgrami>
<dersProgrami>
<DersID>3</DersID>
<DersAdi>9</DersAdi>
</dersProgrami>
<dersProgrami>
<DersID>4</DersID>
<DersAdi>16</DersAdi>
</dersProgrami>
</ArrayOfDersProgrami>
As you see there is five data but as i said when i debug i see 12 data in my array.
I scope data variable "data = XMLHandler.data;" and i see two arrayList, dersAdi and dersID. Then i scope dersAdi, i see array = Object[12], modCount = 5, size = 5. Then i scope array = Obj.. i see [0, 1, 4, 9, 16, null, null, null, null, null, null, null].
What is that mean? I got 5 datas in my xml but there is 12 datas.
And What i want;
I need some suggestion and i'm close to deadline.
This project is my season

It’s a normal behavior I think, you are debugging an ArrayList<> so what you see are the variables into the class ArrayList as you can see there is an array into that initially has size 12 and null cells and also there is an integer that holds the real number of your items (modCount)
so don’t worry about that the class ArrayList is well developed :P
to get sure from what I say you can debug any other ArrayList you will get same behavior.
EDIT:
try to call adapter.notifyDataSetChanged();after setting your adapter to listview

Related

Displaying xml float data

I am trying to create an earthquake watcher app but I can't seem to get the coordinates and other sections from the XML URL to show on my activity when I load the project I know that they are of type float. I have tried different methods and I have no errors on the console so it must be something with the way that I am calling it??
I have added some output and images
package ja.example.mpd1starterearth;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
ListView lvRss;
ArrayList<String> titles;
ArrayList<String> links;
ArrayList<Double> lat;
ArrayList<Double> lon;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvRss = (ListView) findViewById(R.id.lvRss);
titles = new ArrayList<String>();
links = new ArrayList<String>();
lat = new ArrayList<Double>();
lon = new ArrayList<Double>();
lvRss.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Uri uri = Uri.parse(links.get(position));
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
});
new ProcessInBackground().execute();
}
public InputStream getInputStream(URL url)
{
try
{
//openConnection() returns instance that represents a connection to the remote object referred to by the URL
//getInputStream() returns a stream that reads from the open connection
return url.openConnection().getInputStream();
}
catch (IOException e)
{
return null;
}
}
public class ProcessInBackground extends AsyncTask<Integer, Void, Exception>
{
ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);
Exception exception = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog.setMessage("Busy loading rss feed...please wait...");
progressDialog.show();
}
#Override
protected Exception doInBackground(Integer... params) {
try
{
URL url = new URL("http://quakes.bgs.ac.uk/feeds/MhSeismology.xml");
//creates new instance of PullParserFactory that can be used to create XML pull parsers
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
//Specifies whether the parser produced by this factory will provide support
//for XML namespaces
factory.setNamespaceAware(false);
//creates a new instance of a XML pull parser using the currently configured
//factory features
XmlPullParser xpp = factory.newPullParser();
// We will get the XML from an input stream
xpp.setInput(getInputStream(url), "UTF_8");
/* We will parse the XML content looking for the "<title>" tag which appears inside the "<item>" tag.
* We should take into consideration that the rss feed name is also enclosed in a "<title>" tag.
* Every feed begins with these lines: "<channel><title>Feed_Name</title> etc."
* We should skip the "<title>" tag which is a child of "<channel>" tag,
* and take into consideration only the "<title>" tag which is a child of the "<item>" tag
*
* In order to achieve this, we will make use of a boolean variable called "insideItem".
*/
boolean insideItem = false;
// Returns the type of current event: START_TAG, END_TAG, START_DOCUMENT, END_DOCUMENT etc..
int eventType = xpp.getEventType(); //loop control variable
while (eventType != XmlPullParser.END_DOCUMENT)
{
//if we are at a START_TAG (opening tag)
if (eventType == XmlPullParser.START_TAG)
{
//if the tag is called "item"
if (xpp.getName().equalsIgnoreCase("item"))
{
insideItem = true;
}
//if the tag is called "title"
else if (xpp.getName().equalsIgnoreCase("title"))
{
if (insideItem)
{
// extract the text between <title> and </title>
titles.add(xpp.nextText());
}
}
//if the tag is called "link"
else if (xpp.getName().equalsIgnoreCase("link"))
{
if (insideItem)
{
// extract the text between <link> and </link>
links.add(xpp.nextText());
}
}
else if(xpp.getName().equalsIgnoreCase("geo:lat")){
if(insideItem){
//extract the text between <geo:lat> and </geo:lat>
lat.add(Double.valueOf(xpp.nextText()));
}
}
else if(xpp.getName().equalsIgnoreCase("geo:long")){
if(insideItem) {
//extract the text between <geo:lat> and </geo:lat>
lon.add(Double.valueOf(xpp.nextText()));;
} }
}
//if we are at an END_TAG and the END_TAG is called "item"
else if (eventType == XmlPullParser.END_TAG && xpp.getName().equalsIgnoreCase("item"))
{
insideItem = false;
}
eventType = xpp.next(); //move to next element
}
}
catch (MalformedURLException e)
{
exception = e;
}
catch (XmlPullParserException e)
{
exception = e;
}
catch (IOException e)
{
exception = e;
}
return exception;
}
#Override
protected void onPostExecute(Exception s) {
super.onPostExecute(s);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, titles);
lvRss.setAdapter(adapter);
progressDialog.dismiss();
}
}
}
Your code to parse data from the URL is totally correct. You do not see all data all the activity because this line of code.
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, titles);
You pass titles arraylist to the adapter, that why you only see all title xml value in the activity.
Solution: The simple way is format the data which connect from 4 array list titles, links, lat, lon.
/**
* This method will format data from titles, links, lat, lon arraylist.
*/
private List<String> formatDataBeforeDisplayOnListView(){
List<String> list = new ArrayList<>();
StringBuilder sb = new StringBuilder();
int size = titles.size();
for (int i = 0; i < size; ++i) {
String title = titles.get(i);
String link = links.get(i);
Double geoLat = lat.get(i);
Double getLon = lon.get(i);
sb.append("title: ").append(title).append("\n")
.append("link: ").append(link).append("\n")
.append("geo-lat: ").append(geoLat).append("\n")
.append("geo-lon: ").append(getLon);
list.add(sb.toString());
}
return list;
}
Then change your code to
// Comment-out this line
// ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, titles);
List<String> items = formatDataBeforeDisplayOnListView();
ArrayAdapter<String> adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, items);
Note: If you want to display each item listview in a better design/UI then you should write a custom adapter class instead of ArrayAdapter.
Updated: Based on Jase's comment
First, declare a new class named Item
public class Item {
private String title;
private String link;
private Double lat;
private Double lon;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public Double getLat() {
return lat;
}
public void setLat(Double lat) {
this.lat = lat;
}
public Double getLon() {
return lon;
}
public void setLon(Double lon) {
this.lon = lon;
}
#Override
public String toString() {
return (new StringBuilder()).append("title: ").append(title).append("\n")
.append("link: ").append(link).append("\n")
.append("geo-lat: ").append(lat).append("\n")
.append("geo-lon: ").append(lon).toString();
}
}
Then, change your activity code to
public class MainActivity extends AppCompatActivity {
ListView lvRss;
ArrayList<Item> mItems = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvRss = (ListView) findViewById(R.id.lvRss);
lvRss.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// TODO: Process clicked item here
Item item = (Item) parent.getItemAtPosition(position);
Uri uri = Uri.parse(item.getLink());
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
});
new ProcessInBackground().execute();
}
public InputStream getInputStream(URL url) {
try {
//openConnection() returns instance that represents a connection to the remote object referred to by the URL
//getInputStream() returns a stream that reads from the open connection
return url.openConnection().getInputStream();
} catch (IOException e) {
return null;
}
}
public class ProcessInBackground extends AsyncTask<Integer, Void, Exception> {
ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);
Exception exception = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog.setMessage("Busy loading rss feed...please wait...");
progressDialog.show();
}
#Override
protected Exception doInBackground(Integer... params) {
try {
URL url = new URL("http://quakes.bgs.ac.uk/feeds/MhSeismology.xml");
//creates new instance of PullParserFactory that can be used to create XML pull parsers
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
//Specifies whether the parser produced by this factory will provide support
//for XML namespaces
factory.setNamespaceAware(false);
//creates a new instance of a XML pull parser using the currently configured
//factory features
XmlPullParser xpp = factory.newPullParser();
// We will get the XML from an input stream
xpp.setInput(getInputStream(url), "UTF_8");
/* We will parse the XML content looking for the "<title>" tag which appears inside the "<item>" tag.
* We should take into consideration that the rss feed name is also enclosed in a "<title>" tag.
* Every feed begins with these lines: "<channel><title>Feed_Name</title> etc."
* We should skip the "<title>" tag which is a child of "<channel>" tag,
* and take into consideration only the "<title>" tag which is a child of the "<item>" tag
*
* In order to achieve this, we will make use of a boolean variable called "insideItem".
*/
boolean insideItem = false;
// Returns the type of current event: START_TAG, END_TAG, START_DOCUMENT, END_DOCUMENT etc..
int eventType = xpp.getEventType(); //loop control variable
Item item = null;
while (eventType != XmlPullParser.END_DOCUMENT) {
//if we are at a START_TAG (opening tag)
if (eventType == XmlPullParser.START_TAG) {
//if the tag is called "item"
if (xpp.getName().equalsIgnoreCase("item")) {
insideItem = true;
item = new Item();
}
//if the tag is called "title"
else if (xpp.getName().equalsIgnoreCase("title")) {
if (insideItem) {
// extract the text between <title> and </title>
item.setTitle(xpp.nextText());
}
}
//if the tag is called "link"
else if (xpp.getName().equalsIgnoreCase("link")) {
if (insideItem) {
// extract the text between <link> and </link>
item.setLink(xpp.nextText());
}
} else if (xpp.getName().equalsIgnoreCase("geo:lat")) {
if (insideItem) {
//extract the text between <geo:lat> and </geo:lat>
item.setLat(Double.valueOf(xpp.nextText()));
}
} else if (xpp.getName().equalsIgnoreCase("geo:long")) {
if (insideItem) {
//extract the text between <geo:lat> and </geo:lat>
item.setLon(Double.valueOf(xpp.nextText()));
}
}
}
//if we are at an END_TAG and the END_TAG is called "item"
else if (eventType == XmlPullParser.END_TAG && xpp.getName().equalsIgnoreCase("item")) {
insideItem = false;
mItems.add(item);
}
eventType = xpp.next(); //move to next element
}
} catch (MalformedURLException e) {
exception = e;
} catch (XmlPullParserException e) {
exception = e;
} catch (IOException e) {
exception = e;
}
return exception;
}
#Override
protected void onPostExecute(Exception s) {
super.onPostExecute(s);
ArrayAdapter<Item> adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, mItems);
lvRss.setAdapter(adapter);
progressDialog.dismiss();
}
}
}
You are comparing tag name with space in it thus equalsIgnoreCase() will always return false as geo:lang will not be equal to geo :lat.
Just test this code.
String s = "geo:lang";
System.out.println(""+s.equalsIgnoreCase("geo :long"));
You need to remove space in between o and : for both cases eg.equalsIgnoreCase("geo:long")

How can I manage to arrange an ArrayList of a custom Object in alphabetical order, which contains two different strings?

Now in detail. I am writing an App for a dictionary. For that I have created a custom Object called Word. This Word contains the term and its' corresponding translation:
public class Word implements Serializable {
private int _id;
private int wordType;
private String engWordSi;
private String okyWordPl;
private String engWordPl;
private String okyWordSi;
private String engEx;
private String okyEx;
/** Creates a custom class, which allows save a term, it's translation, as well as the plural and example in both
* languages
* #param _id saves the Id of the Word in the Database
* #param engWordSi saves the English translation of the word
* #param okyWordSi saves the Oshikwanyama translation of the word
* #param wordType saves the type of word in form of a number:
* 0 = phrase; 1 = noun; 2 = verb; 3 = adjective; 4 = pronoun; 5 = other
*/
public Word(int _id, int wordType, String engWordSi, String okyWordSi){
this._id = _id;
this.wordType = wordType;
this.engWordSi = engWordSi;
this.okyWordSi = okyWordSi;
}public int get_id(){
return _id;
}
public void set_id(int i){
_id = i;
}
public int getWordType(){
return wordType;
}
public void setWordType(int i){
if(i < 0 || i > 6){
return;
}
wordType = i;
}
public String getEngWordSi(){
return engWordSi;
}
public void setEngWordSi(String word){
engWordSi = word;
}
public String getOkyWordSi(){
return okyWordSi;
}
public void setOkyWordSi(String word){
okyWordSi = word;
}
public String getEngWordPl(){
return engWordPl;
}
public void setEngWordPl(String word){
engWordPl = word;
}
public String getOkyWordPl(){
return okyWordPl;
}
public void setOkyWordPl(String word){
okyWordPl = word;
}
public String getEngEx(){
return engEx;
}
public void setEngEx(String word){
engEx = word;
}
public String getOkyEx(){
return okyEx;
}
public void setOkyEx(String word){
okyEx = word;
}
The data is loaded via a php file connected to the database. The ORDER BY statement only allows me to choose one language to order the results by. But what I need is, that the search term, which might be found in words of both languages, defines if the English word or the Oshikwanyama word is the word which is being arranged in the order. I have check which translation to use in each case. My guess would be to do it in onPostExecute(). The data is returned by the PHP file in the JSON format. From there I put them into an ArrayList.
private class Query extends AsyncTask<Void, Void, Void>{
#Override
protected void onPostExecute(Void aVoid) {
try{
JSONArray jsonArray = new JSONArray(result);
for (int i = 0; i < jsonArray.length(); i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
Word word = new Word(jsonObject.getInt("_id"), jsonObject.getInt("type"), jsonObject.getString("eng"), jsonObject.getString("oky") );
arrayList.add(word);
Log.d("JSON", word.toString());
}
}catch (JSONException e){
e.printStackTrace();
}
ProgressBar bar = (ProgressBar) findViewById(R.id.bar);
bar.setVisibility(View.GONE);
Button button = (Button) findViewById(R.id.SearchButton);
button.setVisibility(View.VISIBLE);
super.onPostExecute(aVoid);
if (arrayList.isEmpty()){
Toast.makeText(SearchActivity.this, "Unfortunately there were no results, the missing word was sent to our developers.", Toast.LENGTH_LONG).show();
return;
}
Intent intent = new Intent(SearchActivity.this, ResultActivity.class);
ItemDetailsWrapper wrapper = new ItemDetailsWrapper(arrayList);
intent.putExtra("results", wrapper);
intent.putExtra("term", searchTerm);
startActivity(intent);
}
InputStream inputStream = null;
String result = "";
#Override
protected void onPreExecute() {
if (arrayList != null){
arrayList.clear();}
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... voids) {
try{
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(uri.toString());
//httpPost.setEntity(new UrlEncodedFormEntity(null));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
inputStream = httpEntity.getContent();
}
catch (UnsupportedEncodingException e1){
e1.printStackTrace();
} catch (ClientProtocolException e2){
e2.printStackTrace();
}catch (IllegalStateException e3){
e3.printStackTrace();
}catch (IOException e4){
e4.printStackTrace();
}try{
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder stringBuilder = new StringBuilder();
String line = null;
while ((line = bufferedReader.readLine()) != null){
stringBuilder.append(line + "\n");
}
inputStream.close();
result = stringBuilder.toString();
}catch (IOException e){
e.printStackTrace();
}
return null;
}
}}
I already have a place to check whether the term searched for is contained in the English or Oshikwanyama word. There I use it to define the flag used in the layout.
public class WordAdapter extends ArrayAdapter<Word> {
private Context mContext;
private List<Word> wordList = new ArrayList<>();
private int srcCode;
private String term;
/** uses words and puts them into a list
*
* #param context stores the context of the calling activity
* #param list stores the ArrayList that was passed into the constructor, and which contains the
* content
* #param searchTerm stores the term that was searched for in SearchActivity to later compare it
* to the contents of the Word and to arrange the correct flag for the source
* language
*/
public WordAdapter(#NonNull Context context, ArrayList<Word> list, String searchTerm) {
super(context, 0 , list);
mContext = context;
wordList = list;
term = searchTerm;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View listItem = convertView;
if(listItem == null){
listItem = LayoutInflater.from(mContext).inflate(R.layout.list_item,parent,false);}
final Word currentWord = wordList.get(position);
//Add Images for the flags of the countries and the flag
final TextView sourceTerm = (TextView) listItem.findViewById(R.id.searchTerm);
final TextView translationTerm = (TextView) listItem.findViewById(R.id.translationTerm);
ImageView flag = (ImageView) listItem.findViewById(R.id.src_flag);
ImageButton button = (ImageButton) listItem.findViewById(R.id.flag);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getContext(), EditorActivity.class);
intent.putExtra("mode", "report");
intent.putExtra("id", currentWord.get_id());
intent.putExtra("source", sourceTerm.getText());
intent.putExtra("trans", translationTerm.getText());
getContext().startActivity(intent);
}
});
if (currentWord.getOkyWordPl() == null){
currentWord.setOkyWordPl("");
}
if (currentWord.getEngWordPl() == null){
currentWord.setEngWordPl("");
}
if (currentWord.getEngWordSi().contains(term) || currentWord.getEngWordPl().contains(term)){
srcCode = 0;
}
if (currentWord.getOkyWordSi().contains(term) || currentWord.getOkyWordPl().contains(term)){
srcCode = 1;
}
if (srcCode == 0){
sourceTerm.setText(currentWord.getEngWordSi());
translationTerm.setText(currentWord.getOkyWordSi());
flag.setImageResource(R.drawable.britain);
}
if (srcCode == 1){
sourceTerm.setText(currentWord.getOkyWordSi());
translationTerm.setText(currentWord.getEngWordSi());
flag.setImageResource(R.drawable.namibia);
}
return listItem;
}}
Thank you in advance. :)
EDIT:
Adding example Words:
1.
EngWordSi: good
OkyWordSi: nawa
wordType: 2
2.
EngWordSi: good morning
OkyWordSi: wa lele po?
wordType: 0
3.
EngWordSi: morning
OkyWordSi: ongula
WordType: 1
what you can do is, sort your object property like below in your adapter,
public WordAdapter(#NonNull Context context, ArrayList<Word> list, String searchTerm) {
super(context, 0 , list);
mContext = context;
wordList = list;
term = searchTerm;
Collections.sort(list, new Comparator<Word>() {
#Override
public int compare(Word word1, word2) {
return word1.getEngWordSi().compareToIgnoreCase(word2.getEngWordSi());
}
});
}
this is helpful to you.
Here is my demo code
public class Main {
static class Word{
String prority1;
#Override
public String toString() {
return "Word{" +
"prority1='" + prority1 + '\'' +
'}';
}
}
public static void main(String[] args) {
ArrayList<Word> words = new ArrayList<>();
Word word;
for (int i = 0; i < 5; i++) {
word =new Word();
word.prority1 = "aaaa"+(5-i);
words.add(word);
System.out.println("wrod "+i+" is "+word);
}
Collections.sort(words, new Comparator<Word>() {
#Override
public int compare(Word o1, Word o2) {
int ret = o1.prority1.compareTo(o2.prority1);
if (ret > 0) {
return 1;
} else if (ret < 0) {
return -1;
}
return 0;
}
});
System.out.println("after sort check words");
for (Word w : words) {
System.out.println("check word:"+w);
}
}
}
and following is console's output:
wrod 0 is Word{prority1='aaaa5'}
wrod 1 is Word{prority1='aaaa4'}
wrod 2 is Word{prority1='aaaa3'}
wrod 3 is Word{prority1='aaaa2'}
wrod 4 is Word{prority1='aaaa1'}
after sort check words
check word:Word{prority1='aaaa1'}
check word:Word{prority1='aaaa2'}
check word:Word{prority1='aaaa3'}
check word:Word{prority1='aaaa4'}
check word:Word{prority1='aaaa5'}
Hope that can help you.

Checkbox not updating in my RecyclerView when it's supposed to

I made a video demo of the problem here: https://www.youtube.com/watch?v=u9G4IVemayE
As you se in the video there is a checkbox in my recyclerview list item.
This checkbox needs to be checked, when the user choose to save a event to the database. But it set the checkbox to checked in the list item, when then user returns from the activity he enteres when he clicks on a item.
notifyDataSetChanged(); and recyclerView.invalidate() hasn't helped either, I have put them many different places in my attempt. The checkbox is only updated when I restart my app.
EventActivity where the list item is shown and saved from:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_saveToDb:
DbHelper.getInstance(EventActivity.this).saveToDb(eventID, title, description, subtitle, start, end, 1, url, imgURL);
//1 in the parameters means that it shall have a checked box. 0:unchecked
MainActivity.databaseList.add(new Event(eventID, title, description, subtitle, start, end, url, imgURL, 1));
checkBox.setChecked(true);
//this checkbox is for an activity layout. nevermind it.
break;
}
}
This is in MainActivity:
// I have tried to call this method different places.
public void initRecyclerView(List<Event> list) {
rvAdapter = new RvAdapter(list, this);
recyclerView.setAdapter(rvAdapter);
rvAdapter.notifyDataSetChanged();
}
**From the RecyclerView Adapter class where i set the checkbox if 1 or 0 **
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
if(list.get(position).getIsDb() == 1){
holder.checkBox.setChecked(true);
}else{
holder.checkBox.setChecked(false);
}
}
The whole MainActivity class:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
dbHelper = new DbHelper(this);
preferences = PreferenceManager.getDefaultSharedPreferences(this);
showListPref = preferences.getInt("SHOW_LIST", 3);
databaseList = new ArrayList<>();
jsonList = new ArrayList<>();
//Vi loader dataen fra start af, så de er klar til at vises frem når som helst og hurtigt
loadDatabaseData(this);
new JsonParser().execute();
toolbar = (Toolbar) findViewById(R.id.toolbar2);
toolbar.setTitleTextColor(Color.WHITE);
toolbar.showOverflowMenu();
setSupportActionBar(toolbar);
getSupportActionBar().setIcon(R.drawable.ic_location_city);
getSupportActionBar().setTitle(" Events in Aarhus");
/*
Sørger huske den valgte liste efter appen er lukket og vise den valgte igen når appen åbnes igen
og sætter også titlen på toolbaren efter hvilken database der vises.
*/
if (showListPref == 2) {
initRecyclerView(databaseList);
getSupportActionBar().setTitle(" Events in Aarhus (Database)");
} else if (showListPref == 3) {
initRecyclerView(jsonList);
getSupportActionBar().setTitle(" Events in Aarhus (JSON)");
}
}
/*
Her loader vi de data der er gemt i databasen og gemmer dem i List<Event> databaseList.
databaseList bruges til adapteren for recyclerviewet så dataen fra databasen kan vises i recyclerviwet.
*/
public void loadDatabaseData(Context context) {
dbHelper = new DbHelper(context);
sqLiteDatabase = dbHelper.getWritableDatabase();
Cursor c = sqLiteDatabase.rawQuery("SELECT * FROM " + DbHelper.DATABASE_NAME, null);
EventCurserWrapper wrapper = new EventCurserWrapper(c);
checkID = new ArrayList<>();
if (c.moveToFirst()) {
while (!c.isAfterLast()) {
databaseList.add(new Event(wrapper.getEvent().getEventID(), wrapper.getEvent().getTitle(), wrapper.getEvent().subtitle, wrapper.getEvent().getDescrption(), wrapper.getEvent().startTime, wrapper.getEvent().endTime, wrapper.getEvent().url, wrapper.getEvent().getImgURL(), wrapper.getEvent().isDb));
checkID.add(wrapper.getEvent().eventID);
c.moveToNext();
}
}
c.close();
}
/*
Denne metode bruger list parameteren til at skifte mellem de forskellige
lister når man fra menuen på toolbaren vælger om man vil se events fra JSON eller Databasen.
*/
public void initRecyclerView(List<Event> list) {
rvAdapter = new RvAdapter(list, this);
recyclerView.setAdapter(rvAdapter);
rvAdapter.notifyDataSetChanged();
}
/*
Async task bruges her til at loade json data og gemme dem i en arraylist
og køre asynkron med appens "mainthread".
*/
private class JsonParser extends AsyncTask<String, Void, String> {
HttpURLConnection conn;
URL url = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
Toast.makeText(MainActivity.this, "LOADING DATA FROM API", Toast.LENGTH_LONG).show();
}
#Override
protected String doInBackground(String... params) {
try {
url = new URL(URL);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream inputStream = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
return (result.toString());
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (Exception ee) {
ee.printStackTrace();
}
return "";
}
#Override
protected void onPostExecute(String s) {
try {
JSONObject object = new JSONObject(s);
JSONArray events = object.getJSONArray("events");
for (int x = 0; x < events.length(); x++) {
JSONObject object1 = events.getJSONObject(x);
String eventID = object1.getString(EVENT_ID);
String title = object1.getString(TITLE);
String subtitle = object1.getString(SUBTITLE);
String description = object1.getString(DESCRIPTION);
String url = object1.getString(EVENT_URL);
String imgURL = object1.getString(PICTURE_URL);
JSONArray dateArray = object1.getJSONArray(DATES);
for (int y = 0; y < dateArray.length(); y++) {
JSONObject dateObject = dateArray.getJSONObject(y);
long start = dateObject.getLong(START);
long end = dateObject.getLong(END);
if (!title.isEmpty()) {
/*
Da datoen vi får fra JSON er i UNIX/Epoch format, så
konverter vi denne dato til rigtig "kalender" dato med koden nedunder
*/
Date date = new Date(start * 1000);
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.getDefault());
format.setTimeZone(TimeZone.getDefault());
String startdate = format.format(date);
Date date2 = new Date(end * 1000);
SimpleDateFormat format2 = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.getDefault());
format2.setTimeZone(TimeZone.getDefault());
String enddate = format2.format(date2);
/*
Her tjekker vi om de events der netop bliver loaded fra JSON om de i forvejen
eksister i databasen og hvis de gør, sættes flag til 1 og denne værdi bruges
i adapteren til at sætte checkboxen til true : 0 = false;
*/
int flag = 0;
if (DbHelper.getInstance(MainActivity.this).getEventIDs(eventID).contains(eventID) == true) {
flag = 1;
}
jsonList.add(new Event(eventID, title, subtitle, description, startdate, enddate, url, imgURL, flag));
}
}
}
rvAdapter.notifyDataSetChanged();
Toast.makeText(MainActivity.this, events.length() + " events loaded", Toast.LENGTH_LONG).show();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.listfragmentDemo:
startActivity(new Intent(MainActivity.this, MainActivityTest.class));
break;
case R.id.menu_showDatabase:
preferences.edit().putInt("SHOW_LIST", 2).apply();
initRecyclerView(databaseList);
getSupportActionBar().setTitle("Events in Aarhus (Database)");
break;
case R.id.menu_showJson:
preferences.edit().putInt("SHOW_LIST", 3).apply();
initRecyclerView(jsonList);
getSupportActionBar().setTitle("Events in Aarhus (JSON)");
break;
}
return super.onOptionsItemSelected(item);
}
/*
OnResume kaldes i stedet for onRestart, da vi kan være sikker på kaldes i activitens lifecyclus
som du engang fortalte på tavlen (;
*/
#Override
protected void onResume() {
super.onResume();
rvAdapter.notifyDataSetChanged();
}
}
The whole adapter class for RecyclerView:
public class RvAdapter extends RecyclerView.Adapter<RvAdapter.ViewHolder> {
private static List<Event> list;
private static Context context;
public RvAdapter(List<Event> list, Context context) {
this.list = list;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View v = inflater.inflate(R.layout.list_item, parent, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.title.setText(list.get(position).getTitle());
holder.eventTime.setText("START: " + list.get(position).getStartTime() + " END: " + list.get(position).getEndTime());
/*
Hvis eventet eksisterer i databasen (1) så sæt checkboxen =true
*/
if(list.get(position).getIsDb() == 1){
holder.checkBox.setChecked(true);
}else{
holder.checkBox.setChecked(false);
}
}
#Override
public int getItemCount() {
return list.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView title, eventTime;
CheckBox checkBox;
public ViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.item_event_title);
eventTime = (TextView) itemView.findViewById(R.id.item_event_time);
checkBox = (CheckBox)itemView.findViewById(R.id.item_event_checkbox);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Intent intent = new Intent(context, EventActivity.class);
intent.putExtra("EVENT_ID", list.get(getAdapterPosition()).getEventID());
intent.putExtra("TITLE", list.get(getAdapterPosition()).getTitle());
intent.putExtra("START", list.get(getAdapterPosition()).getStartTime());
intent.putExtra("END", list.get(getAdapterPosition()).getEndTime());
intent.putExtra("DESCRIPTION", list.get(getAdapterPosition()).getDescrption());
intent.putExtra("SUBTITLE", list.get(getAdapterPosition()).getSubtitle());
intent.putExtra("URL", list.get(getAdapterPosition()).getUrl());
intent.putExtra("IMG_URL", list.get(getAdapterPosition()).getImgURL());
intent.putExtra("isDatabase", list.get(getAdapterPosition()).getIsDb());
intent.putExtra("POS", getAdapterPosition());
context.startActivity(intent);
}
}
}
I found the solution in a single line: MainActivity.jsonList.get(position).setIsDb(1);
I get the position of the clicked item with intentExtras: position = getIntent().getIntExtra("POS", 0); in the EventActivity where an event is shown after a click on a liste-item
and use that position to update the isDB variable of the model data.
Then onReturn to MainActivity I just call: notifyDataSetChanged();
the isDB variable is updated to 1 inside here after I save to the database.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_saveToDb:
DbHelper.getInstance(EventActivity.this).saveToDb(eventID, title, description, subtitle, start, end, 1, url, imgURL);
MainActivity.databaseList.add(new Event(eventID, title, description, subtitle, start, end, url, imgURL, 1));
//Update isDB of the current model data for the seleceted list_item
MainActivity.jsonList.get(position).setIsDb(1);
//This is for another checkbox. nevermind it
checkBox.setChecked(true);
break;
}
}
You are updating boolean value in db but your model item in Main Activity is not updated since RecyclerView is already instantiated.
There are several methods to solve this:
Reload RecyclerView data model in MainActivity onResume method.
Notify from EventActivity to MainActivity the change and update item in RecyclerView (class LocalBroadcast manager can help you in this) (BEST APPROACH)
Always read from db to get updated bool value (in method -> list.get(position).getIsDb()) (WORST APPROACH)

Custom adapter not updating gridview

I am writing an app to pull movie data from the MovieDB api and display the information in a GridView.
When the app first loads I would expect the view to populate initially, but it does not. I have a sort option in the menu bar and when the sort option is set the first time the GridView is populated by movies in order of popularity, as it should initially, but regardless of what sort criteria is actually selected.
I have used the logs to determine that the correct data is being retrieved from the API and being processed properly, so I have to assume that the adapter is not updating the view properly.
Why isn't the view showing initially or updating as it should?
FilmFragment.java:
public class FilmFragment extends Fragment {
private ArrayList<FilmParcelable> filmParcels = new ArrayList<FilmParcelable>();
private ImageAdaptor mFilmAdaptor;
protected String[] sortOptions = {
"popularity.desc",
"vote_average.desc"
};
protected String sortBy = sortOptions[0];
private final String LOG_TAG = FilmFragment.class.getSimpleName();
public FilmFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
if (savedInstanceState == null || !savedInstanceState.containsKey("films")){
updateFilms();
mFilmAdaptor = new ImageAdaptor(getActivity(),filmParcels);
} else {
filmParcels = savedInstanceState.getParcelableArrayList("films");
mFilmAdaptor = new ImageAdaptor(getActivity(),filmParcels);
}
// allow fragment to handle menu events
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
inflater.inflate(R.menu.filmfragment, menu);
}
public boolean onOptionsItemSelected(MenuItem item){
//Handle action bar item clicks. The action bar will
//automatically handle clicks on the Home/Up button, so long
//as you specify a parent activity in AndroidManifest.xml
int id = item.getItemId();
if (id == R.id.action_sort){
showSortDialog();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onSaveInstanceState(Bundle outState){
outState.putParcelableArrayList("films", filmParcels);
super.onSaveInstanceState(outState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
// Find GridView to populate with poster images
GridView gridView = (GridView) rootView.findViewById(R.id.gridView);
// Set the adaptor of the GridView to my ImageAdaptor
gridView.setAdapter(mFilmAdaptor);
updateAdaptor();
return rootView;
}
// Update movie data in case there is a change in the "sort by" option
// Or the fragment is started with no saved data
public void updateFilms(){
new FetchFilmTask().execute();
}
public void updateAdaptor(){
mFilmAdaptor.clear();
mFilmAdaptor.addAll(filmParcels);
mFilmAdaptor.notifyDataSetChanged();
}
// Show dialog sort pop up
public void showSortDialog(){
DialogFragment dialog = new SortDialog();
dialog.setTargetFragment(this, 0);
dialog.show(getActivity().getSupportFragmentManager(), "SortDialog");
}
// If a fragment or activity called by this fragment returns to this fragment,
// Get the information returned via the intent
public void onActivityResult(int requestCode, int resultCode, Intent data){
if (requestCode == 0){
int mSelected = data.getIntExtra("Selected Option", -1);
if (mSelected != -1){
sortBy = sortOptions[mSelected];
updateFilms();
updateAdaptor();
}
}
}
// Class to get JSON data from The Movie Database API
public class FetchFilmTask extends AsyncTask<Void, Void, FilmParcelable[]> {
private final String LOG_TAG = FetchFilmTask.class.getSimpleName();
private final String MOVIE_DB_API_KEY = "e1968ef8ba074d7d5bf07a59de8b2310";
protected FilmParcelable[] doInBackground(Void... params){
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain raw JSON response as a string
String movieDBStr = null;
try {
// Construct URL for Movie DB query
Uri.Builder builder = new Uri.Builder();
builder.scheme("http")
.authority("api.themoviedb.org")
.appendPath("3")
.appendPath("discover")
.appendPath("movie")
.appendQueryParameter("api_key", MOVIE_DB_API_KEY)
.appendQueryParameter("sort_by", sortBy);
String myUrl = builder.build().toString();
Log.d(LOG_TAG, myUrl);
URL url = new URL(myUrl);
// Create the request to The Movie DB, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
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) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
return null;
}
movieDBStr = buffer.toString();
} catch (IOException e){
Log.e(LOG_TAG, "Error: ", e);
return null;
} finally {
if (urlConnection != null){
urlConnection.disconnect();
}
if (reader != null){
try{
reader.close();
} catch (final IOException e){
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
try {
return getFilmDataFromJson(movieDBStr);
} catch (JSONException e){
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
return null;
}
/**
* Take the String representing the complete forecast in JSON Format and
* pull out the data we need to construct the Strings needed for the wireframes.
*
* Fortunately parsing is easy: constructor takes the JSON string and converts it
* into an Object hierarchy for us.
*/
private FilmParcelable[] getFilmDataFromJson(String movieDBStr)
throws JSONException {
// JSON objects that need to be extracted
final String MDB_RESULTS = "results";
final String MDB_ID = "id";
final String MDB_SYNOPSIS = "overview";
final String MDB_RELEASE = "release_date";
final String MDB_POSTER = "poster_path";
final String MDB_TITLE = "title";
final String MDB_RATING = "vote_average";
JSONObject filmJson = new JSONObject(movieDBStr);
JSONArray filmArray = filmJson.getJSONArray(MDB_RESULTS);
FilmParcelable[] resultFilms = new FilmParcelable[filmArray.length()];
for (int i = 0; i < filmArray.length(); i++){
// Data needed by the FilmParcelable
int id;
String title;
String releaseDate;
String posterUrl;
Double voteAverage;
String plotSynopsis;
JSONObject film = filmArray.getJSONObject(i);
id = film.getInt(MDB_ID);
plotSynopsis = film.getString(MDB_SYNOPSIS);
releaseDate = film.getString(MDB_RELEASE);
posterUrl = "http://image.tmdb.org/t/p/w300" + film.getString(MDB_POSTER);
title = film.getString(MDB_TITLE);
voteAverage = film.getDouble(MDB_RATING);
Log.d(LOG_TAG, title);
Log.d(LOG_TAG, posterUrl);
resultFilms[i] = new FilmParcelable(id, title, releaseDate, posterUrl, voteAverage, plotSynopsis);
}
return resultFilms;
}
#Override
protected void onPostExecute(FilmParcelable[] result){
if (result != null){
filmParcels = new ArrayList<>(Arrays.asList(result));
}
}
}
}
ImageAdaptor.java:
public class ImageAdaptor extends ArrayAdapter<FilmParcelable> {
public ImageAdaptor(Activity context, ArrayList<FilmParcelable> filmParcels){
super(context, 0, filmParcels);
}
public View getView(int position, View convertView, ViewGroup parent){
Context context= getContext();
View gridView;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
String mUrl = getItem(position).getUrl();
if (convertView == null) {
gridView = inflater.inflate(R.layout.gridview_film_layout, parent, false);
// Find the image view from the gridview_film_layout
ImageView posterView = (ImageView) gridView.findViewById(R.id.grid_item_image);
// Set the image view to contain image located at mUrl
Picasso.with(getContext()).load(mUrl).into(posterView);
} else {
gridView = convertView;
}
return gridView;
}
}
accordingly to the code you posted you are returning over and over the same cell of your GridView. You should have those two lines
ImageView posterView = (ImageView) gridView.findViewById(R.id.grid_item_image);
Picasso.with(getContext()).load(mUrl).into(posterView);
out of the if/else guard:
if (convertView == null) {
// inflate
} else {
// gridView = convertView;
}
ImageView posterView = (ImageView) gridView.findViewById(R.id.grid_item_image);
Picasso.with(getContext()).load(mUrl).into(posterView);
return gridView;
I was attempting to update the adapter after populating the arraylist used for the adapter. However the arraylist was populated and updated in the background so the code:
updateFilms();
updateAdaptor();
was causing the adaptor to update before the data had completed loading in the background.
After fixing that Blackbelt's solution was correct.

Parse xml data into hashtable and displaying in listview?

I have a problem. I have multiple records that after SAX parsing from a xml file that needs to be inserted into the Hashtable and displayed in a listview. I am able to display the data in the listview but all it gives is the same data for all rows in the listview. I think it has something to do with either my coding for the hashtable or my SAX parsing.
This is the xml file I'm trying to retrieve data from online: http://spark.opac.tp.edu.sg/X?op=present&set_no=007584&set_entry=000000001,000000002,000000003,000000004,000000005&format=marc
Below is my handler where i place my data into the hashtable:
ArrayList<Hashtable<String,String>> list = new ArrayList<Hashtable<String,String>>();
Hashtable<String,String> data = new Hashtable<String,String>();
private final String MY_DEBUG_TAG = "Debugging~";
private Boolean in_record = false;
private Boolean in_author = false;
private Boolean in_format = false;
private Boolean in_title = false;
private Boolean in_callNumber = false;
private String format = "";
private String title = "";
private String author = "";
private String callNumber = "";
//private SearchList sList;
//public SearchList getListData() {
// return this.sList;
//}
#Override
public void startDocument() throws SAXException {
// this.sList = new SearchList();
}
#Override
public void endDocument() throws SAXException {
// Nothing to do
}
/** Called when tag starts ( ex:- <name>AndroidPeople</name>
* -- <name> )*/
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if(localName.equalsIgnoreCase("record")) {
this.in_record = true;
}
else
if (localName.equalsIgnoreCase("fixfield")) {
if (attributes.getValue("id").equalsIgnoreCase("FMT")) {
this.in_format = true;
}
}
else
if(localName.equalsIgnoreCase("varfield")) {
if(attributes.getValue("id").equalsIgnoreCase("100")) {
this.in_author = true;
}
else
if(attributes.getValue("id").equalsIgnoreCase("245")) {
this.in_title = true;
}
else
if(attributes.getValue("id").equalsIgnoreCase("099")) {
this.in_callNumber = true;
}
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
StringBuffer sb = new StringBuffer();
String finalString;
String originalString = "";
String chars = new String(ch, start, length);
chars = chars.trim();
if (this.in_format) {
sb.append(chars);
finalString = sb.toString();
this.format = finalString;
}
else
if (this.in_author) {
if(!(chars.equals(""))) {
sb.append(chars);
finalString = sb.toString();
originalString = this.author + finalString;
this.author = originalString;
}
}
else
if (this.in_title) {
if(!(chars.equals(""))) {
sb.append(chars);
finalString = sb.toString();
originalString = this.title + finalString;
this.title = originalString;
}
}
else
if (this.in_callNumber) {
if(!(chars.equals(""))) {
sb.append(chars);
finalString = sb.toString();
this.callNumber = finalString;
}
}
}
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (localName.equalsIgnoreCase("record")) {
this.in_record=false;
}
else
if (localName.equalsIgnoreCase("fixfield")) {
if (this.in_format) {
//set the foundCharacter to Hashtable
data.put("format", this.format);
//sList.setFormat(this.format);
Log.d(MY_DEBUG_TAG,"Format = " + this.format);
this.in_format = false;
}
}
else
if(localName.equalsIgnoreCase("varfield")) {
if (this.in_author) {
//set the foundCharacter to Hashtable
data.put("author", this.author);
//sList.setAuthor(this.author);
Log.d(MY_DEBUG_TAG,"Author = " + this.author);
this.in_author = false;
}
else
if (this.in_title) {
//set the foundCharacter to Hashtable
data.put("title", this.title);
//sList.setTitle(this.title);
Log.d(MY_DEBUG_TAG,"Title = " + this.title);
this.in_title = false;
}
else
if (this.in_callNumber) {
//set the foundCharacter to Hashtable
data.put("callNumber", this.callNumber);
//sList.setCallNumber(this.callNumber);
Log.d(MY_DEBUG_TAG,"Call Number = " + this.callNumber);
this.in_callNumber = false;
}
}
//add the hashtable into ArrayList
list.add(data);
}
Any suggestions guys?
I don't have time to read completly your code ...
But this is a simple example :
ListView myListView;
myListView = (ListView) findViewById(R.id.mylistview);
ArrayList<HashMap<String, String>> listItem = new ArrayList<HashMap<String, String>>();
HashMap<String, String> map;
//load your data
String[][] items = database.getItems("Blog");
//check if the database was empty
if(items != null){
for(int i = 0; i < items[0].length; i++) {
map = new HashMap<String, String>();
map.put("pubdate", items[2][0]);
map.put("title", items[0][i]);
map.put("description", items[1][i]);
listItem.add(map);
}
//Creation of a SimpleAdapter to put items in your list (listitems) in your listview
// You need to have a xml file called list_full_news_item with elements
// called android:id="#+id/title" etc.
SimpleAdapter mSimpleAdaptor = new SimpleAdapter (this.getBaseContext(), listItem, R.layout.list_full_news_item,
new String[] {"pubdate", "title", "description"}, new int[] {R.id.itemPubdate, R.id.itemTitle, R.id.itemDescription});
//Assign to the listView the created adapter
myListView.setAdapter(mSimpleAdaptor);
}
Hope this will help you to understand.
You should not use the SAX Parser and use the Simple XML Library instead. It has the #ElementMap annotation for exactly this purpose. This turns your entire problem into one annotation and three lines of code to read the XML in. Look at my blog post on including the library in an android project and look at the Simple tutorial if you want to see how to use all of its cool features.
Edit: I just realised that I have answered this question before in one of your previous questions. I'm done trying to convince you to look into Simple XML; but please, stop posting essentially the exact same question in five different ways here; people have helped you already, give you answers and lead you in the right direction. It is now time to read more, experiment and learn.

Categories

Resources