Reputation: 758
I've been struggling with this for about 3 days already and finally I decided to take a risk and ask you guys. The problem is, that I get NullPointerException as you already got from the title. With a debugger I found the source of my problems, so I know exactly what causes that nullpointer: its the variable "doc" of type Document, which you can find in the code below. Sorry for too many words, here is the code
This is the code of my class DomXmlParser
public class DomXmlParser {
Document doc;
String urlLink;
InputStream is;
public DomXmlParser(String url){
this.urlLink = url;
}
public Document getDoc(){
return doc;
}
public void parseXML(InputStream is) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
doc = builder.parse(is);
} catch (Exception e) {
e.printStackTrace();
}
}
public void getXML(){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try{
URL url = new URL(urlLink);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setReadTimeout(15000);
conn.setConnectTimeout(15000);
conn.setDoInput(true);
conn.connect();
is = conn.getInputStream();
Log.d("InputStreamContents", is.toString());
parseXML(is);
is.close();
}catch(Exception e){
e.printStackTrace();
}
}
});
thread.start();
}
}
So, in MainActivity I call getXml() method and then getDoc().
public void parseDom(){
DomXmlParser parser = new DomXmlParser(xmlUrl);
parser.getXML();
doc = parser.getDoc();
NodeList list = doc.getElementsByTagName("item");
for (int i = 0; i < list.getLength(); i++){
Node item = list.item(i);
if (item.getNodeType()==Node.ELEMENT_NODE){
Element data = (Element) item;
NodeList dataList = data.getChildNodes();
for (int j = 0; j < dataList.getLength(); i++){
Node p = dataList.item(j);
if (p.getNodeType()==Node.ELEMENT_NODE){
Element title = (Element) p;
Element description = (Element) p;
FeedItem fi = new FeedItem();
fi.setName(title.getTextContent());
fi.setStatus(description.getTextContent());
feedItems.add(fi);
}
}
}
}
}
I debugged my application, and it looks like the getDoc() method returns null. Also it says that the line
NodeList list = doc.getElementsByTagName("item");
returns null. So, the Document doc variable of the DomXmlParser class is null. I know for sure, that InputStream is not null, also everything worked fine when I tried to parse XML via XmlPullParser, so either XML file or link are OK. Hope you help me guys cause neither I, nor google know what to do.
UPDATE: As it was suggested in the answer below, I removed the Thread, and just created a class that exnteds AsyncTask in MainActivity, so now I don't have that NullPointer, but I have the other problem: Out of memory on a 144-byte allocation. And I have no idea what to do with it.
Logs
10-29 00:17:13.139 3258-3258/com.motoharu.cleaningapp E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at com.motoharu.cleaningapp.HomeFragment.parseDom(HomeFragment.java:151)
at com.motoharu.cleaningapp.HomeFragment.initControls(HomeFragment.java:78)
at com.motoharu.cleaningapp.HomeFragment.onStart(HomeFragment.java:70)
at android.support.v4.app.Fragment.performStart(Fragment.java:1528)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:972)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1121)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1484)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:482)
at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1073)
at android.support.v4.view.ViewPager.populate(ViewPager.java:919)
at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1441)
at android.view.View.measure(View.java:16030)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5012)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:314)
at android.view.View.measure(View.java:16030)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5012)
at com.android.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:302)
at android.view.View.measure(View.java:16030)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5012)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:314)
at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2196)
at android.view.View.measure(View.java:16030)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1915)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1109)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1290)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1009)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5508)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
at android.view.Choreographer.doCallbacks(Choreographer.java:562)
at android.view.Choreographer.doFrame(Choreographer.java:532)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:5225)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:741)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
at dalvik.system.NativeStart.main(Native Method)
Upvotes: 1
Views: 1931
Reputation: 758
Well, some kind of answer. As far as the only answer didn't solved my problem I continued googling and found an information saying, that it's better to use not DOM, but SAX parser to parse RSS feed, so I did so. But, eventualy, I faced the same NullPointer problem and I didn't know why. And everything was because that data, which I was getting inside new thread didn't interract with the data outside the Thread, as Sir manouti said. So, his answer solved my problem but with SAX parser this time.
Upvotes: 1
Reputation: 72854
The problem is because getXML
is spawning a new thread that constructs the Document
object referenced by doc
. So after calling parser.getXML()
, the code tries to access the doc
variable using the getDoc()
method, but this variable is still not initialized by that thread.
The solution is to wait for the thread to finish. This can simply be done using a join
. For example, you can create the new Thread
when calling the getXML
method, instead of creating it inside the method itself.
public void getXML(){
try {
URL url = new URL(urlLink);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setReadTimeout(15000);
conn.setConnectTimeout(15000);
conn.setDoInput(true);
conn.connect();
is = conn.getInputStream();
Log.d("InputStreamContents", is.toString());
parseXML(is);
is.close();
}catch(Exception e){
e.printStackTrace();
}
}
In parseDom
final DomXmlParser parser = new DomXmlParser(xmlUrl);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
parser.getXML();
}
});
thread.start();
try {
thread.join(); // wait until above thread finishes
} catch (InterruptedException e) {
// handle the exception here
}
doc = parser.getDoc();
Upvotes: 1