Adamouization Adamouization - 4 months ago 18
Android Question

Retrieving String from class (xml parsing class) to current class

I wrote two classes, one is used to retrieve fields from an XML feed and store them as Strings in the class, and the other class is supposed to retrieve those fields to set the text various TextViews in a xml layout file.

Using Logs, I managed to see that the xml parser class does get the fields from the xml feed since they are printed in the android monitor, but they are not printed in the other class when I try to pass them. I only get the default values I set on these Strings when I initialized them.

I'm probably doing something very wrong but I have no idea, I've been stuck on this issue since yesterday aftertnoon!

Here is the xml parser class which stores the values retrieved:

public class StackAgenceXml {

/**
* fields
*/
private String urlAgenceStringXml = null;
private String nom = "nom";
private String adresse = "adresse";
private String codepostal = "codepostal";
private String ville = "ville";
private String pays = "pays";
private String lat = "lat";
private String lng = "lng";
private String tel = "tel";
private String fax = "fax";
private String email = "email";
private String web = "url";
private String logo = "logo";
private XmlPullParserFactory xmlFactoryObject;
public volatile boolean parsingComplete = false;

/**
* Constructor.
*
* @param url
*/
public StackAgenceXml(String url) {
this.urlAgenceStringXml = url;
}

/**
* @param agenceParser
*/
public void parseXmlAgenceAndStore(XmlPullParser agenceParser) {
int event;
String text = null;

try {
event = agenceParser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
String name = agenceParser.getName();

switch (event) {
case XmlPullParser.START_TAG:
break;

case XmlPullParser.TEXT:
text = agenceParser.getText();
break;

case XmlPullParser.END_TAG:
if (name.equals("nom")) {
nom = text;
} else if (name.equals("adresse")) {
//adresse = agenceParser.getAttributeValue(null, "value");
adresse = text;
} else if (name.equals("codepostal")) {
codepostal = text;
} else if (name.equals("ville")) {
ville = text;
} else if (name.equals("pays")) {
pays = text;
} else if (name.equals("lat")) {
lat = text;
} else if (name.equals("lng")) {
lng = text;
} else if (name.equals("tel")) {
tel = text;
} else if (name.equals("fax")) {
fax = text;
} else if (name.equals("email")) {
email = text;
} else if (name.equals("url")) {
web = text;
} else if (name.equals("logo")) {
logo = text;
} else {
}
break;
}
event = agenceParser.next();
}
parsingComplete = false;
} catch (Exception e) {
e.printStackTrace();
}
Log.i("ex of agency info = ", nom + adresse + codepostal + ville + pays + lat + lng + tel +
fax + email + web + logo);
}

/**
* fetch data from xml url
*/
public void fetchTypesXml() {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
URL url = new URL(urlAgenceStringXml);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setReadTimeout(10000 /*ms*/);
conn.setConnectTimeout(15000 /*ms*/);
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.connect();

InputStream stream = conn.getInputStream();
xmlFactoryObject = XmlPullParserFactory.newInstance();
XmlPullParser myparser = xmlFactoryObject.newPullParser();

myparser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
myparser.setInput(stream, null);

parseXmlAgenceAndStore(myparser);
stream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
}

/**
* GETTERS*
*/
public String getAdresse() {
return adresse;
}
public String getNom() {
return nom;
}

public String getCodepostal() {
return codepostal;
}

public String getVille() {
return ville;
}

public String getPays() {
return pays;
}

public String getLat() {
return lat;
}

public String getLng() {
return lng;
}

public String getTel() {
return tel;
}

public String getFax() {
return fax;
}

public String getEmail() {
return email;
}

public String getWeb() {
return web;
}

public String getLogo() {
return logo;
}
}


Here is the class where I am trying to get the String values from the xml parser:

public class Contact extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {

/**
* fields
*/
private StackAgenceXml stackAgence;
private TextView txtAdresse, txtTel, txtFax, txtWeb;
private String adresse, telephone, fax, website;
//to change agency go to string values and change the id at the end of xml feed url
private String urlAgencesXml = "http://api.immotoolbox.com/xml/2.0/AGENCE/agences/?id=115";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact);

/**fetch xml data*/
stackAgence = new StackAgenceXml(urlAgencesXml);
stackAgence.fetchTypesXml();

/**get references*/
txtAdresse = (TextView) findViewById(R.id.txt_contact_adresse);
txtTel = (TextView) findViewById(R.id.txt_contact_tel);
txtFax = (TextView) findViewById(R.id.txt_contact_fax);
txtWeb = (TextView) findViewById(R.id.txt_contact_web);

/**assign text to textviews*/
adresse = stackAgence.getAdresse() + stackAgence.getCodepostal() + stackAgence.getPays();
telephone = stackAgence.getTel();
fax = stackAgence.getFax();
website = stackAgence.getWeb();

Log.i("contact fields retrieved", adresse + telephone + fax + website);

txtAdresse.setText(adresse);
txtTel.setText(telephone);
txtFax.setText(fax);
txtWeb.setText(website);
}


And finally, here are the logs, you can clearly see that they are retrieved in the xml parser class but not retrieved in the other class since just the default values are printed:

07-07 09:00:49.830 21234-21234/com.example.adam_jaamour.cfimmobilier W/System: ClassLoader referenced unknown path: /data/app/com.example.adam_jaamour.cfimmobilier-2/lib/x86
07-07 09:00:49.941 21234-21234/com.example.adam_jaamour.cfimmobilier W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
07-07 09:00:50.115 21234-21369/com.example.adam_jaamour.cfimmobilier D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true

[ 07-07 09:00:50.119 21234:21234 D/ ]
HostConnection::get() New Host Connection established 0xaff50460, tid 21234


[ 07-07 09:00:50.149 21234:21369 D/ ]
HostConnection::get() New Host Connection established 0xae4473f0, tid 21369
07-07 09:00:50.150 21234-21369/com.example.adam_jaamour.cfimmobilier I/OpenGLRenderer: Initialized EGL, version 1.4
07-07 09:00:52.271 21234-21234/com.example.adam_jaamour.cfimmobilier I/contact fields retrieved: adressecodepostalpaystelfaxurl
07-07 09:00:52.518 21234-21369/com.example.adam_jaamour.cfimmobilier E/Surface: getSlotFromBufferLocked: unknown buffer: 0xae479a00
07-07 09:00:52.600 21234-21405/com.example.adam_jaamour.cfimmobilier I/ex of agency info =: Cristea-Flandrin Immobilier21, boulevard des Moulins98000MonacoMonaco43.742968007.42821350+377 93 30 75 61+377 92 16 71 64cristea@monte-carlo.mchttp://www.agencecristea.comhttp://api.immotoolbox.com/media/cache/xml2_logo/uploads/agences/115/logo-medium.png
07-07 09:03:35.351 21234-21238/com.example.adam_jaamour.cfimmobilier W/art: Suspending all threads took: 8.151ms
07-07 09:05:25.616 21234-21238/com.example.adam_jaamour.cfimmobilier W/art: Suspending all threads took: 8.484ms
07-07 09:05:47.661 21234-21238/com.example.adam_jaamour.cfimmobilier W/art: Suspending all threads took: 5.969ms
07-07 09:06:00.189 21234-21238/com.example.adam_jaamour.cfimmobilier W/art: Suspending all threads took: 5.851ms
07-07 09:06:43.804 21234-21238/com.example.adam_jaamour.cfimmobilier W/art: Suspending all threads took: 16.978ms
07-07 09:07:31.407 21234-21238/com.example.adam_jaamour.cfimmobilier W/art: Suspending all threads took: 7.489ms


I hope this is enough for anyone to help me out here, comment under the questions if you need anything else, thank you! :)

Answer

What is happening is that you are running the XML parser with a new thread (HttpURLConnection is an asynchonous action). So the mian thread is calling the fetchTypesXml() function and retrieving the info before the data is actually received.

In fact, in you logcat, you are getting the log of the activity before than the log of the class.

07-07 09:00:52.271 21234-21234/com.example.adam_jaamour.cfimmobilier I/contact fields retrieved: adressecodepostalpaystelfaxurl
07-07 09:00:52.518 21234-21369/com.example.adam_jaamour.cfimmobilier E/Surface: getSlotFromBufferLocked: unknown buffer: 0xae479a00
07-07 09:00:52.600 21234-21405/com.example.adam_jaamour.cfimmobilier I/ex of agency info =: Cristea-Flandrin Immobilier21, boulevard des Moulins98000MonacoMonaco43.742968007.42821350+377 93 30 75 61+377 92 16 71 64cristea@monte-carlo.mchttp://www.agencecristea.comhttp://api.immotoolbox.com/media/cache/xml2_logo/uploads/agences/115/logo-medium.png

To solve the problem you can implement an interface for call a function inside the activity when the info is ready. I will sow you some pseudocode..

Interface (pseudocode):

public interface XMLResponse {
    public void sendXMLData(String adresse, String telephone ,String fax, String website, ...);
}

Your function need to receive the listener (pseucode):

public void fetchTypesXml(XMLResponse listener) {
    ...

    // when you finished to request and parse all the data, call the function inside the listener
    listener.sendXMLData(adresse, telephone, fax, website ...);

    }

Declare the interface in your activity and call your method with the activity (pseudocode):

public class Contact extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, XMLResponse {

    ...

   stackAgence.fetchTypesXml(this);

    ...

And finally, in your activity, implements the interface method (pseudocode):

@Override 
public void sendXMLData(String adrs, String cdpostal, String pays, String tel, String fx, String web) { 

    adresse = adrs + cdpostal + pays; 
    telephone = tel; 
    fax = fx; 
    website = web; 
    txtAdresse.setText(adresse); 
    txtTel.setText(telephone); 
    txtFax.setText(fax); 
    txtWeb.setText(website); 
}
Comments