Azrie Bakri Azrie Bakri - 4 months ago 13
Java Question

ArrayList doesn't display value outside of method where the data storing happens

I have this class where it process XML and store it inside an

ArrayList<FeedItem>
. I can display the array content in the method where I store the data but when I try to display the array in another method it did not pass the
if
checking indicating that the ArrayList is empty. Because of this, I can't create a ListView because it'll return the same error. I hope someone can briefly explain to me what is wrong.

ReadRSS.java

public class ReadRSS extends AsyncTask<Void, Void, Void> {

//Initialize progress dialog
Context context;
String address;
ProgressDialog progressDialog;
XmlPullParserFactory xmlPullParserFactory;
volatile boolean parsingComplete = true;
ArrayList<FeedItem> feedItems;
ListView listView;

public ReadRSS(Context context, ListView listView, String retrieveAddress) {
//Create a new progress dialog
this.listView = listView;
this.address = retrieveAddress;
this.context = context;
progressDialog = new ProgressDialog(context);
progressDialog.setMessage("Loading....");

}

// Runs in UI before background thread is called
@Override
protected void onPreExecute() {
//Display progress dialog
progressDialog.show();
super.onPreExecute();
}

// This is run in a background thread
@Override
protected Void doInBackground(Void... voids) {
fetchXML();
return null;
}

// This is called from background thread but runs in UI
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}

// This runs in UI when background thread finishes
@Override
protected void onPostExecute(Void aVoid) {
//Dismiss progress dialog
super.onPostExecute(aVoid);
progressDialog.dismiss();


/*if(listView != null) {
CustomAdapter customAdapter = new CustomAdapter(context, R.layout.activity_listview, feedItems);
listView.setAdapter(customAdapter);

}*/

if(feedItems != null){
//Gives error
for(int i = 0; i < feedItems.size(); i++) {
Log.d("Title", feedItems.get(i).getTitle());
Log.d("Date", feedItems.get(i).getPubDate());
}

}

}

//New Build

public void parseXMLAndStoreIt(XmlPullParser myParser) {
int event;
String text;
String title = null;
String date = null;

feedItems = new ArrayList<FeedItem>();

try {
event = myParser.getEventType();

while (event != XmlPullParser.END_DOCUMENT) {
String tagName = myParser.getName();

switch (event){

case XmlPullParser.START_TAG:
if(tagName.equalsIgnoreCase("item")){
int eventChild = myParser.next();
//int innerLoop = 1;

String tagNameChild = "";
while(eventChild != XmlPullParser.END_DOCUMENT){

if(eventChild == XmlPullParser.START_TAG){
tagNameChild = myParser.getName();
// Output Test
//Log.d("Tag ", tagNameChild);
}

else if (eventChild == XmlPullParser.TEXT){

text = myParser.getText();
// Output Test
//Log.d("Test ", text);


if(tagNameChild.equalsIgnoreCase("title")){

title = text;
// Output Test
//Log.d("Title ", myParser.getText());
}
else if(tagNameChild.equalsIgnoreCase("pubDate")){

date = text;
// Output Test
//Log.d("PubDate ", myParser.getText());

}
}

else if (eventChild == XmlPullParser.END_TAG){


if(myParser.getName().equalsIgnoreCase("item")){

feedItems.add(new FeedItem(title,date));
// Output Test
//Log.d("Test ", title);
}

tagNameChild = "";

}

eventChild = myParser.next();

//innerLoop++;
}

//Output Test
/*for(int i = 0; i < feedItems.size(); i++) {
Log.d("Title", feedItems.get(i).getTitle());
Log.d("Date", feedItems.get(i).getPubDate());
}*/
}

break;

case XmlPullParser.TEXT:
break;

case XmlPullParser.END_TAG:
break;

}

event = myParser.next();

}

parsingComplete = false;
}

catch (Exception e) {
e.printStackTrace();
}
}

public void fetchXML(){
Thread thread = new Thread(new Runnable(){
@Override
public void run() {

try {
URL url = new URL(address);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setReadTimeout(10000 );
conn.setConnectTimeout(15000 );
conn.setRequestMethod("GET");
conn.setDoInput(true);

// Starts the query
conn.connect();
InputStream stream = conn.getInputStream();

xmlPullParserFactory = XmlPullParserFactory.newInstance();
XmlPullParser myparser = xmlPullParserFactory.newPullParser();

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

parseXMLAndStoreIt(myparser);
stream.close();
}

catch (Exception e) {
}
}
});
thread.start();
}
}

Answer

You are calling fetchXML() from doInBackground, but fetchXML() starts a new thread and then immediately returns. Then doInBackground() immediately returns and onPostExecute() is called. However, at that point, the thread launched by fetchXML() has not had time to finish, so feedItems has not been properly set.

That's the wrong way to use an AsyncTask. Instead, you should do the fetching directly in the doInBackground() thread. Just rewrite fetchXML() to do the fetching itself, rather than launch a separate thread to do the fetching.