1
00:00:04,160 --> 00:00:06,600
Alright, so let's now run the app and

2
00:00:06,600 --> 00:00:09,510
see if it works, and I'm going to open

3
00:00:09,510 --> 00:00:11,759
logcat. I'm gonna make sure that I've

4
00:00:11,759 --> 00:00:14,309
still got my filter set mainactivity

5
00:00:14,309 --> 00:00:17,279
pipe downdata, which I have, and I've

6
00:00:17,279 --> 00:00:19,289
also got Regex checked as well,

7
00:00:19,289 --> 00:00:21,779
which would be the default. Now, as long

8
00:00:21,779 --> 00:00:23,070
as I haven't left the emulator in

9
00:00:23,070 --> 00:00:25,170
airplane mode, it should all work. I'm

10
00:00:25,170 --> 00:00:26,160
going to clear - well I don't need to

11
00:00:26,160 --> 00:00:27,869
clear the logcat first because it is

12
00:00:27,869 --> 00:00:31,109
clear, but if not, do so - and we'll run it and

13
00:00:31,109 --> 00:00:35,340
see what happens. And we'll tab over to

14
00:00:35,340 --> 00:00:43,680
our app. And that doesn't look good.

15
00:00:43,680 --> 00:00:46,739
There's no XML being logged and also no

16
00:00:46,739 --> 00:00:48,930
stack trace to give us any indication of

17
00:00:48,930 --> 00:00:50,760
what's gone wrong. Now there are

18
00:00:50,760 --> 00:00:53,430
two errors, as we can see here, showing up

19
00:00:53,430 --> 00:00:56,010
from MainActivity. And if we click on

20
00:00:56,010 --> 00:01:00,989
the top one - the top error here - that

21
00:01:00,989 --> 00:01:03,180
takes us to, as you can see, our onPost

22
00:01:03,180 --> 00:01:06,570
Execute function, and to the call to the

23
00:01:06,570 --> 00:01:09,150
parseApplications.parse function call.

24
00:01:09,150 --> 00:01:11,460
So with just that information in the

25
00:01:11,460 --> 00:01:13,470
logcat, things like this can be really

26
00:01:13,470 --> 00:01:16,740
hard to debug, but fortunately, that isn't

27
00:01:16,740 --> 00:01:18,930
all that's available. The problem is, and

28
00:01:18,930 --> 00:01:20,520
I alluded to that, is that we're

29
00:01:20,520 --> 00:01:22,619
filtering the logcat, and that means that

30
00:01:22,619 --> 00:01:24,360
we don't see any entries being logged,

31
00:01:24,360 --> 00:01:27,000
unless they come from MainActivity or

32
00:01:27,000 --> 00:01:29,490
from DownloadData. So I'm going to click

33
00:01:29,490 --> 00:01:31,350
on this little x here to clear the

34
00:01:31,350 --> 00:01:33,659
filter window, and once I do that - well to

35
00:01:33,659 --> 00:01:35,310
clear the filter rather - and once I do

36
00:01:35,310 --> 00:01:36,689
that, you can see that we've got the

37
00:01:36,689 --> 00:01:39,270
complete log. Now that's actually gonna

38
00:01:39,270 --> 00:01:41,369
give us far more to go on, so remember

39
00:01:41,369 --> 00:01:44,310
that. If you filter the logcat, make sure

40
00:01:44,310 --> 00:01:45,780
you clear the filters when your app

41
00:01:45,780 --> 00:01:46,320
crashes,

42
00:01:46,320 --> 00:01:48,000
otherwise, you'll be trying to find the

43
00:01:48,000 --> 00:01:49,770
cause of the crash with very little

44
00:01:49,770 --> 00:01:51,000
information to go on.

45
00:01:51,000 --> 00:01:53,700
Now before we cleared the filter, there

46
00:01:53,700 --> 00:01:55,560
was nothing to indicate that parse was

47
00:01:55,560 --> 00:01:57,869
even being called. Now that could have

48
00:01:57,869 --> 00:02:00,149
caused a lot of confusion when trying to

49
00:02:00,149 --> 00:02:02,520
debug this. So now that we've cleared the

50
00:02:02,520 --> 00:02:05,250
filter, we can see, if we scroll up and have a

51
00:02:05,250 --> 00:02:08,128
bit of a look here, or we can actually

52
00:02:08,128 --> 00:02:10,318
see anyway - we can see that parse clearly

53
00:02:10,318 --> 00:02:11,520
has logged the XML because that was

54
00:02:11,520 --> 00:02:13,080
showing as soon as I cleared the filter.

55
00:02:13,080 --> 00:02:13,650
And

56
00:02:13,650 --> 00:02:15,090
we can also see, if we scroll down and

57
00:02:15,090 --> 00:02:16,920
have a bit of a look here, that the

58
00:02:16,920 --> 00:02:22,739
actual error is here on line 29: null

59
00:02:22,739 --> 00:02:25,290
cannot be cast to non-null type Java dot

60
00:02:25,290 --> 00:02:26,610
lang.String. So I'm gonna click on that,

61
00:02:26,610 --> 00:02:30,720
and that takes us to the line that's got

62
00:02:30,720 --> 00:02:32,700
the TODO that I talked about, in the

63
00:02:32,700 --> 00:02:35,129
previous video. So the error in the

64
00:02:35,129 --> 00:02:37,620
logcat was kotlin.TypeCastException,

65
00:02:37,620 --> 00:02:40,140
and you can see this on screen: null cannot

66
00:02:40,140 --> 00:02:43,079
be cast to non-null type java.lang

67
00:02:43,079 --> 00:02:46,230
dot String. So what that essentially means is

68
00:02:46,230 --> 00:02:48,180
that we're trying to call the toLowercase

69
00:02:48,180 --> 00:02:51,900
method on a value that's null. Now xpp

70
00:02:51,900 --> 00:02:54,690
dot name starts off null until something's

71
00:02:54,690 --> 00:02:56,940
being read, and null doesn't have any

72
00:02:56,940 --> 00:02:59,760
properties or methods. So to fix the

73
00:02:59,760 --> 00:03:02,250
problem, we're going to use the safe call

74
00:03:02,250 --> 00:03:04,470
operator that we've used before, and it

75
00:03:04,470 --> 00:03:06,269
makes sure that we don't attempt to call

76
00:03:06,269 --> 00:03:08,489
methods on things that are null. So all

77
00:03:08,489 --> 00:03:10,560
we really need to do here, is actually,

78
00:03:10,560 --> 00:03:13,680
after the xpp.name - we're going to

79
00:03:13,680 --> 00:03:17,489
put a question mark after that, and then I'm

80
00:03:17,489 --> 00:03:18,810
going to remove the TODO because we've,

81
00:03:18,810 --> 00:03:22,410
effectively, fixed that now. If we run

82
00:03:22,410 --> 00:03:29,010
this again, this time we're actually

83
00:03:29,010 --> 00:03:31,500
getting our formatted data showing in

84
00:03:31,500 --> 00:03:33,030
the logcat, so clearly that was the issue

85
00:03:33,030 --> 00:03:35,549
that we've managed to fix. So if we

86
00:03:35,549 --> 00:03:37,079
scroll back now up to the start of the

87
00:03:37,079 --> 00:03:41,549
log, we can see this onCreate starting

88
00:03:41,549 --> 00:03:43,729
and then there's doinBackground: starts.

89
00:03:43,729 --> 00:03:46,109
We've got a response code of two

90
00:03:46,109 --> 00:03:51,790
hundred, and if we scroll down a bit further,

91
00:03:51,790 --> 00:03:54,019
then you can see that the parser is

92
00:03:54,019 --> 00:03:57,470
logging the XML that it receives. And

93
00:03:57,470 --> 00:03:58,580
that's working just like it did before,

94
00:03:58,580 --> 00:04:00,739
but after that, if we keep scrolling down

95
00:04:00,739 --> 00:04:03,700
again now, past the XML, we can see that

96
00:04:03,700 --> 00:04:06,560
the log entries from our parse method

97
00:04:06,560 --> 00:04:08,450
showing here; Starting tag for feed,

98
00:04:08,450 --> 00:04:11,030
Starting tag for ID, Ending tag for ID,

99
00:04:11,030 --> 00:04:13,159
and so on. So, every time there was a

100
00:04:13,159 --> 00:04:15,200
START_TAG or END_

101
00:04:15,200 --> 00:04:17,389
TAG event, it got logged. So the

102
00:04:17,389 --> 00:04:18,949
logcat's showing the name of each tag

103
00:04:18,949 --> 00:04:22,100
in the XML, as the PullParser sets event

104
00:04:22,100 --> 00:04:24,770
type to START_TAG and END

105
00:04:24,770 --> 00:04:27,500
_TAG. Now if we scroll down 

106
00:04:27,500 --> 00:04:32,720
round about 20 or so lines down, we get

107
00:04:32,720 --> 00:04:35,479
over here, the Starting tag for entry. So

108
00:04:35,479 --> 00:04:37,160
from there to the end of the entry tag,

109
00:04:37,160 --> 00:04:38,630
the code's looking for the tags we're

110
00:04:38,630 --> 00:04:40,820
interested in, and storing their values

111
00:04:40,820 --> 00:04:43,550
in the FeedEntry object. Now we can make

112
00:04:43,550 --> 00:04:44,750
life a little bit easier by using

113
00:04:44,750 --> 00:04:47,139
control F, or command F on a Mac, to

114
00:04:47,139 --> 00:04:50,539
search the logcat for entry. So I'll do

115
00:04:50,539 --> 00:04:56,030
that - entry. When I press ENTER, it jumps

116
00:04:56,030 --> 00:04:57,680
to the first, it'll actually jump

117
00:04:57,680 --> 00:04:59,630
to the first occurrence automatically. But if

118
00:04:59,630 --> 00:05:02,750
I press ENTER, it should jump to an

119
00:05:02,750 --> 00:05:04,430
occurrence of entry that's in the XML at

120
00:05:04,430 --> 00:05:06,440
the top, and I can use the down arrow on

121
00:05:06,440 --> 00:05:08,510
the toolbar to jump to the next one. So

122
00:05:08,510 --> 00:05:10,039
come over here and go down to the next one,

123
00:05:10,039 --> 00:05:14,300
and I can also use this little plus

124
00:05:14,300 --> 00:05:16,970
button over here, to highlight all the

125
00:05:16,970 --> 00:05:19,610
places where entry appears. And then they

126
00:05:19,610 --> 00:05:21,139
will stay highlighted, as long as I don't

127
00:05:21,139 --> 00:05:23,330
close the search pane, and that's great

128
00:05:23,330 --> 00:05:24,590
for scrolling up and down the logcat,

129
00:05:24,590 --> 00:05:26,240
seeing where the entries start and end. So

130
00:05:26,240 --> 00:05:30,039
I'll click on that, and scroll up and down,

131
00:05:30,039 --> 00:05:32,210
and you can see entries highlighted

132
00:05:32,210 --> 00:05:35,270
there for us automatically, which is pretty

133
00:05:35,270 --> 00:05:38,360
cool. So the parser is going

134
00:05:38,360 --> 00:05:41,360
through the entire XML stream, responding

135
00:05:41,360 --> 00:05:43,099
to the information it finds in there.

136
00:05:43,099 --> 00:05:45,949
Now our code's checking to see where the

137
00:05:45,949 --> 00:05:48,380
new tag's found, and when it ends, and

138
00:05:48,380 --> 00:05:51,470
pulling out the values we need. Now most

139
00:05:51,470 --> 00:05:53,330
of the tags start and end straight away,

140
00:05:53,330 --> 00:05:56,570
but when we get an entry tag starting, we

141
00:05:56,570 --> 00:05:58,699
stay in the entry because all the other

142
00:05:58,699 --> 00:06:01,130
tags are nested inside it. And once it's

143
00:06:01,130 --> 00:06:03,620
gone through updated, ID, title and so on -

144
00:06:03,620 --> 00:06:05,479
processing all those tags -

145
00:06:05,479 --> 00:06:07,669
it eventually gets the closing tag for

146
00:06:07,669 --> 00:06:10,460
entry. There's releasedate and content,

147
00:06:10,460 --> 00:06:12,830
and then we get the end tag for entry. So

148
00:06:12,830 --> 00:06:13,969
you can see that, as we're going down

149
00:06:13,969 --> 00:06:16,039
here, the starting tag, all the various

150
00:06:16,039 --> 00:06:18,750
tags there,

151
00:06:18,750 --> 00:06:20,680
releasedate, as I said there, and

152
00:06:20,680 --> 00:06:22,660
eventually the tag, ending tag for

153
00:06:22,660 --> 00:06:24,759
content and then ending tag for entry,

154
00:06:24,759 --> 00:06:26,699
and then we've got another one starting.

155
00:06:26,699 --> 00:06:29,440
So once we get the end tag for an entry,

156
00:06:29,440 --> 00:06:31,300
we know that all its fields have been

157
00:06:31,300 --> 00:06:33,849
processed and we can add the object to

158
00:06:33,849 --> 00:06:36,310
the list. And that's why most of the code

159
00:06:36,310 --> 00:06:38,590
does its processing when we get to the

160
00:06:38,590 --> 00:06:41,020
END_TAG events. In other words,

161
00:06:41,020 --> 00:06:43,750
that's why we added a lot of coding in

162
00:06:43,750 --> 00:06:46,449
this particular area - the END

163
00:06:46,449 --> 00:06:49,319
_TAG tag, if that makes sense.

164
00:06:49,319 --> 00:06:51,819
So what I can also do is come over here,

165
00:06:51,819 --> 00:06:54,400
to the find, and instead of just leaving

166
00:06:54,400 --> 00:06:56,110
entry in there, I can actually put a pipe

167
00:06:56,110 --> 00:06:59,500
and a name as well. And I still want to

168
00:06:59,500 --> 00:07:00,580
make sure that the Regex

169
00:07:00,580 --> 00:07:02,530
checkbox is checked, but this time it's

170
00:07:02,530 --> 00:07:04,300
the regex that's appropriate for the

171
00:07:04,300 --> 00:07:08,199
search, not the regex for our filter. And you

172
00:07:08,199 --> 00:07:09,759
can see now that it highlights - just

173
00:07:09,759 --> 00:07:11,590
scroll down the file a little bit more,

174
00:07:11,590 --> 00:07:15,219
so we can see it a bit better - it's

175
00:07:15,219 --> 00:07:17,379
highlighting both name and entry because

176
00:07:17,379 --> 00:07:19,780
we've used the pipe to be able to search

177
00:07:19,780 --> 00:07:21,789
for either of those. Now I've done that

178
00:07:21,789 --> 00:07:23,560
to show why we keep track of when we're

179
00:07:23,560 --> 00:07:25,810
inside an entry tag, so I'm scrolling

180
00:07:25,810 --> 00:07:28,330
back up - scroll right back until we get

181
00:07:28,330 --> 00:07:31,039
to the first entry.

182
00:07:31,039 --> 00:07:34,309
So there's the first entry, so if we keep

183
00:07:34,309 --> 00:07:36,319
scrolling back up to the top, to our

184
00:07:36,319 --> 00:07:39,139
very first entry.

185
00:07:39,139 --> 00:07:43,129
Alright, so our first entry is here, but

186
00:07:43,129 --> 00:07:45,080
you see above that, there's a name tag

187
00:07:45,080 --> 00:07:46,909
that's not part of that first entry

188
00:07:46,909 --> 00:07:48,620
there. But we don't want to use that name -

189
00:07:48,620 --> 00:07:50,960
it's the name of the whole feed, not one

190
00:07:50,960 --> 00:07:53,150
of the individual applications. So

191
00:07:53,150 --> 00:07:54,919
because we only use the tag values if

192
00:07:54,919 --> 00:07:57,590
inEntry is true, the code will ignore

193
00:07:57,590 --> 00:07:59,719
this one. Alright, now if we scroll down

194
00:07:59,719 --> 00:08:02,389
to the bottom here, we can see the

195
00:08:02,389 --> 00:08:03,979
summary of the application records that

196
00:08:03,979 --> 00:08:07,189
we've created, as well. So there should be

197
00:08:07,189 --> 00:08:09,379
ten applications there, because we chose

198
00:08:09,379 --> 00:08:11,659
the Top 10 feed, and we can see the data

199
00:08:11,659 --> 00:08:13,969
nicely formatted into the individual

200
00:08:13,969 --> 00:08:17,629
feeds. Now one thing I want to mention is

201
00:08:17,629 --> 00:08:20,719
the imageURL. There are actually three

202
00:08:20,719 --> 00:08:23,150
image tags in each entry, and our code

203
00:08:23,150 --> 00:08:25,340
picks up the value of each one, then

204
00:08:25,340 --> 00:08:27,139
overrides it when the next one comes

205
00:08:27,139 --> 00:08:29,569
around. Because the image tags appear in

206
00:08:29,569 --> 00:08:32,179
size order in the XML, we end up with the

207
00:08:32,179 --> 00:08:35,719
URLs for the 100 by 100 image. But you

208
00:08:35,719 --> 00:08:37,279
shouldn't really rely on the ordering of

209
00:08:37,279 --> 00:08:40,099
tags in an XML feed. The XML would have

210
00:08:40,099 --> 00:08:42,589
been invalid, whatever order the

211
00:08:42,589 --> 00:08:45,230
image URLs had appeared. So going back to

212
00:08:45,230 --> 00:08:48,339
Chrome, and if we look for those images -

213
00:08:48,339 --> 00:08:53,000
so look for image - you'll notice here,

214
00:08:53,000 --> 00:08:54,550
that the image has got a height

215
00:08:54,550 --> 00:08:57,500
attribute. So if we were interested in a

216
00:08:57,500 --> 00:08:59,510
particular image size, we could check

217
00:08:59,510 --> 00:09:01,640
that attribute and only store the URL

218
00:09:01,640 --> 00:09:04,790
for the height we wanted. But I'm not

219
00:09:04,790 --> 00:09:06,260
going to check the attributes in this

220
00:09:06,260 --> 00:09:07,970
code, because it'll make it too

221
00:09:07,970 --> 00:09:10,220
specific to these Apple feeds, and you

222
00:09:10,220 --> 00:09:11,240
may want to experiment with different

223
00:09:11,240 --> 00:09:14,089
feeds. But if you really want to test the

224
00:09:14,089 --> 00:09:16,399
attributes, you'd usually get attribute

225
00:09:16,399 --> 00:09:18,380
value function of the PullParser, and

226
00:09:18,380 --> 00:09:20,420
you can search online for ways to do

227
00:09:20,420 --> 00:09:22,640
that. Now I'm going to pop up a slide for a

228
00:09:22,640 --> 00:09:24,890
few seconds, showing the changes I made

229
00:09:24,890 --> 00:09:27,079
to test the height attribute, and load

230
00:09:27,079 --> 00:09:28,790
the small imageURL - the one with the height

231
00:09:28,790 --> 00:09:31,040
of 53. So if you want to choose a

232
00:09:31,040 --> 00:09:33,199
specific image and get stuck, you can

233
00:09:33,199 --> 00:09:36,610
refer to this slide for one way to do it.

234
00:09:36,610 --> 00:09:39,079
Alright, so that's our application -

235
00:09:39,079 --> 00:09:41,000
downloading the feed and parsing out the

236
00:09:41,000 --> 00:09:43,910
information we're interested. The next

237
00:09:43,910 --> 00:09:45,940
step, now, is to display it on the screen.

238
00:09:45,940 --> 00:09:48,740
Now we could add ten TextView widgets to

239
00:09:48,740 --> 00:09:50,779
the screen, and put the details of each

240
00:09:50,779 --> 00:09:52,160
application in them,

241
00:09:52,160 --> 00:09:53,660
but then the app wouldn't work for the

242
00:09:53,660 --> 00:09:56,690
Top 25 feed, or for other feeds that could

243
00:09:56,690 --> 00:09:59,209
return, perhaps, hundreds of records. So in

244
00:09:59,209 --> 00:10:00,709
the next few videos, we're gonna look at

245
00:10:00,709 --> 00:10:02,420
one way of dealing with displaying data

246
00:10:02,420 --> 00:10:04,430
when you don't know, in advance, how many

247
00:10:04,430 --> 00:10:07,370
records it's going to be. So, as always, I'll

248
00:10:07,370 --> 00:10:10,389
see you in the next video.

