So I have ViewModel with a method to get data using context. But in testing the data is null because possibly there is no context when testing.
The code is as follow:
This is testing ViewModel code
public class FilmViewTest {
private FilmView filmView;
#Before
public void setUp() {
Application context = Mockito.mock(Application.class);
filmView = new FilmView(context);
FilmData filmData = new FilmData(context);
}
// ubah poster menjadi link
#Test
public void getFilms() {
List<ResultsItem> films = filmView.getFilms();
assertNotNull(films);
assertEquals(10, films.size());
}
}
and here is the ViewModel itself
public class FilmView extends AndroidViewModel {
public FilmView(#NonNull Application application) {
super(application);
}
private Context context = getApplication().getApplicationContext();
private FilmData filmData = new FilmData(context);
public List<ResultsItem> getFilms() {
return FilmData.generateFilms();
}
}
the data class
public class FilmData {
private static Context context;
public FilmData(Context context) {
FilmData.context = context;
}
public static ArrayList<ResultsItem> generateFilms() {
ArrayList<ResultsItem> courses = new ArrayList<>();
courses.add(new ResultsItem(
"A Star is Born",
"Seasoned musician Jackson Maine discovers — " +
"and falls in love with — struggling artist Ally." +
" She has just about given up on her dream to make it big as a singer — until Jack coaxes her into the spotlight. But even as Ally's career takes off, the personal " +
"side of their relationship is breaking down, as Jack fights an ongoing battle with his own internal demons.",
context.getResources().getDrawable(R.drawable.poster_a_start_is_born),
346, " February 19, 2019", 75, 50));
courses.add(new ResultsItem("Aquaman",
"Once home to the most advanced civilization on Earth, Atlantis is now an underwater kingdom ruled by the power-hungry King Orm. With a vast army at his disposal, Orm plans to conquer the remaining oceanic people and then the surface world. " +
"Standing in his way is Arthur Curry, Orm's half-human, " +
"half-Atlantean brother and true heir to the throne.",
context.getResources().getDrawable(R.drawable.poster_aquaman),
238, "December 21, 2018", 68, 60));
courses.add(new ResultsItem("Bohemian Rhapsody ",
"Singer Freddie Mercury, guitarist Brian May, drummer Roger Taylor and bass guitarist John Deacon take the music world by storm when they form the rock 'n' roll band Queen in 1970. Hit songs become instant classics. When Mercury's increasingly wild lifestyle starts to spiral out of control, " +
"Queen soon faces its greatest challenge yet – " +
"finding a way to keep the band together amid the success and excess.",
context.getResources().getDrawable(R.drawable.poster_bohemian),
892, "November 2, 2018", 80, 299));
courses.add(new ResultsItem("Alita: Battle Angel ",
"When Alita awakens with no memory of who she is in a future world she does not recognize, she is taken in by Ido, a compassionate doctor who realizes that" +
" somewhere in this abandoned cyborg " +
"shell is the heart and soul of a young woman with an extraordinary past.\n",
context.getResources().getDrawable(R.drawable.poster_alita),
289, "January 31, 2019", 69, 15 ));
courses.add(new ResultsItem(
"Cold Pursuit",
"The quiet family life of Nels Coxman, a snowplow driver, is upended after his son's murder. Nels begins a vengeful hunt for Viking, the drug lord he holds responsible for the killing, eliminating Viking's associates one by one. As Nels draws closer to Viking, his actions bring even more unexpected and violent consequences, as he proves that revenge is all in the execution.",
context.getResources().getDrawable(R.drawable.poster_cold_persuit),
54, "February 7, 2019", 54, 219));
courses.add(new ResultsItem(
"Creed",
"The former World Heavyweight Champion Rocky Balboa serves as a trainer and mentor to Adonis Johnson, the son of his late friend and former rival Apollo Creed.",
context.getResources().getDrawable(R.drawable.poster_creed),
129, "November 25, 2015", 73, 281));
courses.add(new ResultsItem("Fantastic Beasts: The Crimes of Grindelwald",
"Gellert Grindelwald has escaped imprisonment and has begun gathering followers to his cause—elevating wizards above all non-magical beings. The only one capable of putting a stop to him is the wizard he once called his closest friend, Albus Dumbledore. However, Dumbledore will need to seek help from the wizard who had thwarted Grindelwald once before, his former student Newt Scamander, who agrees to help, unaware of the dangers that lie ahead. Lines are drawn as love and loyalty are tested, even among the truest friends and family, in an increasingly divided wizarding world.",
context.getResources().getDrawable(R.drawable.poster_crimes),
123, "November 14, 2018", 69, 210));
courses.add(new ResultsItem("Glass ",
"In a series of escalating encounters, former security guard David Dunn uses his supernatural abilities to track Kevin Wendell Crumb, a disturbed man who has twenty-four personalities. Meanwhile, the shadowy presence of Elijah Price emerges as an orchestrator who holds secrets critical to both men.",
context.getResources().getDrawable(R.drawable.poster_glass).getCurrent(),
213, "January 16, 2019", 66, 190));
courses.add(new ResultsItem("How to Train Your Dragon ",
"As the son of a Viking leader on the cusp of manhood, shy Hiccup Horrendous Haddock III faces a rite of passage: he must kill a dragon to prove his warrior mettle. But after downing a feared dragon, he realizes that he no longer wants to destroy it, and instead befriends the beast – which he names Toothless – much to the chagrin of his warrior father",
context.getResources().getDrawable(R.drawable.poster_how_to_train),
319, "March 10, 2010", 77, 219));
courses.add(new ResultsItem(
"Avengers: Infinity War",
"As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.",
context.getResources().getDrawable(R.drawable.poster_infinity_war),
193, "April 25, 2018", 83, 21933));
return courses;
}
}
it gives null error on the methods
java.lang.NullPointerException
at com.example.movietv.film.utils.FilmData.generateFilms(FilmData.java:28)
at com.example.movietv.film.adapter.FilmView.getFilms(FilmView.java:26)
at com.example.movietv.film.adapter.FilmViewTest.getFilms(FilmViewTest.java:32)
Any help would be appreciated! Thanks!
Ideally, you should not be passing entire drawable object into model context.getResources().getDrawable(R.drawable.poster_infinity_war). Instead, just pass the int of the resource as
new ResultsItem("How to Train Your Dragon ",
"As ... father", R.drawable.poster_how_to_train,
319, "March 10, 2010", 77, 219)
Note: You need to change ResultsItem Model accordingly
and then, when you are actually rendering it in an Adapter:
public class MyOrdersAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<MyOrder> restaurantList;
private Context context;
public MyOrdersAdapter(Context context, List<MyOrder> restaurantList) {
this.context = context;
this.restaurantList = restaurantList;
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder viewHolder, int position) {
if(context != null)
holder.data.setBackgroundResource(context.getResources().getDrawable(R.drawable.poster_infinity_war));
}
...
}
This will help you prevent OutOfMemoryException in future
Here is my code:
try{
JSONObject jsonObjitem = new JSONObject(jsonString);
JSONArray phrasemaster = jsonObjitem.getJSONArray("phrases");
for(int i = 0; i<phrasemaster.length();i++){
JSONObject scan = phrasemaster.getJSONObject(i);
int id = scan.getInt("id");
if (id == current){
String question = scan.getString("question");
idoutcome1 = scan.getString("idoutcome1");
idoutcome2 = scan.getString("idoutcome2");
idoutcome3 = scan.getString("idoutcome3");
}
}
} catch (JSONException e) {
e.printStackTrace();
}
The user on launch gets random number, when he press the button he is being moved to another fragment where this number is used to pull item from JSON, this number serves as id.
Each item have another three id's. So when I pull my item with this code I also pull 3 id's from that json item. Now what I want is to output the question string from these id's.
{
"phrases": [
{
"id": 1,
"question": "first item",
"idoutcome1": 2,
"idoutcome2": 3,
"idoutcome3": 4
},
{
"id": 2,
"nameofoption": "item 2",
"question": "some question 2",
"idoutcome1": 5,
"idoutcome2": 6,
"idoutcome3": 7
},
{
"id": 3,
"nameofoption": "item 3",
"question": "some question 3",
"idoutcome1": 8,
"idoutcome2": 9,
"idoutcome3": 10
}
]
}
The thing is that I don't understand how I can reach out to these values.
Edit: illustration of what I'm trying to do.
While parsing I take the idoutcome1,2,3 values and output them on my buttons.
However, I want to output the value written in the nameofoption field instead of these numbers. Just like the example, instead of 2 it should show "left".
The problem is that I have this try that searches for id that it got on the previous page and outputs item with corresponding id. How can I implement it within the course of this try that it would go deeper and depending on the idoutcome's of this JSON item display values from the nameofoption field?
I've solved it in a following way, all of the idoutcome's were put in arraylist, then I've reused the same json parsing code to loop through the items with the respective id's and then output them ti the buttons with settext.
That was my first json experience, thanks for the downvotes.
I am developping an Android application that dialogs with some Google App Engine web-services.
This application implements a Chat Activity which have very a very simple feature: send text.
During debugging I noticed that the messages I was listing from the server were not displayed in the same order I had sent them on my application. My first thought was that the problem was comming from the server.
At first I checked the raw Json I was receiving:
{
"messages": [
{
"message": "test 3",
"author": "daniel",
"message_id": "5724160613416960",
"sent_at": "2014-11-13T09:42:42.861950"
},
{
"message": "test 2",
"author": "daniel",
"message_id": "5649050225344512",
"sent_at": "2014-11-13T09:42:10.390960"
},
{
"message": "test 1",
"author": "daniel",
"message_id": "5178081291534336",
"sent_at": "2014-11-13T09:41:01.998830"
}
],
"kind": "company#chatsItem",
"etag": "\"RUCkC9XynEQNZ2t5E0aa41edXro/xRNtgkWIUbq4zCgmv2iq2fy-UIg\""
}
As you can see, the raw data is correctly ordered. But here comes the funny part. When I add a JSON parser, such as JacksonFactory (or even GsonFactory):
Company.Builder builder = new Company.Builder(AndroidHttp.newCompatibleTransport(), new JacksonFactory(), null);
Company service = builder.build();
ChatsChatCollectionResponse response = service.chats().list(user_id, album_id, token).execute();
List<ChatsChatResponse> messagesResponse = response.getMessages();
Here are the ChatsChatResponse items ordered in the same way as above:
[0] = {com.appspot.com_pany.company.model.ChatsChatResponse#830029063096} size = 4
[0] = {com.google.api.client.util.DataMap$Entry#830029082528}"author" -> "daniel"
[1] = {com.google.api.client.util.DataMap$Entry#830029082552}"message" -> "test 3"
[2] = {com.google.api.client.util.DataMap$Entry#830029082576}"message_id" -> "5724160613416960"
[3] = {com.google.api.client.util.DataMap$Entry#830029082600}"sent_at" -> "2014-11-13T10:57:03.950+01:00"
[1] = {com.appspot.com_pany.company.model.ChatsChatResponse#830029066376} size = 4
[0] = {com.google.api.client.util.DataMap$Entry#830029083616}"author" -> "daniel"
[1] = {com.google.api.client.util.DataMap$Entry#830029083640}"message" -> "test 2"
[2] = {com.google.api.client.util.DataMap$Entry#830029083664}"message_id" -> "5649050225344512"
[3] = {com.google.api.client.util.DataMap$Entry#830029083688}"sent_at" -> "2014-11-13T10:48:40.960+01:00"
[2] = {com.appspot.com_pany.company.model.ChatsChatResponse#830029068008} size = 4
[0] = {com.google.api.client.util.DataMap$Entry#830029084760}"author" -> "daniel"
[1] = {com.google.api.client.util.DataMap$Entry#830029084784}"message" -> "test 1"
[2] = {com.google.api.client.util.DataMap$Entry#830029084808}"message_id" -> "5178081291534336"
[3] = {com.google.api.client.util.DataMap$Entry#830029084832}"sent_at" -> "2014-11-13T10:57:39.830+01:00"
Why is there such a random difference on the "sent_at" field ?
EDIT
I forgot to mention that I am not talking about the 1 hour shift that corresponds to TimeZone, but rather on how random the minutes are.
I'm not sure about the solution, but the explanation seems quite clear: the variation is not random at all, but rather caused by adding everything after the decimal point as milliseconds.
Take the third entry, for example:
2014-11-13T09:41:01.998830
Evidently, the parser reads this as:
hours: 09
minutes: 41
seconds: 01
milliseconds: 998830
Since milliseconds is greater than 1000, it ends up being transformed into 998s 830ms, which when accounting for full minutes is 16m 38s 830ms. Hence:
hours: 09
minutes: 41 + 16
seconds: 01 + 38
milliseconds: 830
Which produces exactly the result you're seeing (modulo timezone adjustment):
2014-11-13T10:57:39.830+01:00
If you have control over the service output (this point is not quite clear from the question wording), the easiest fix would be to output only three digits after the decimal points (i.e. rounding at milliseconds instead of millionths). For the example, this would be 2014-11-13T09:41:01.999.
It might also be possible to fix this on the parser itself, but it would require a bit more research (and ideally, a gist that reproduces the problem).
try setting a custom date format like
Gson gson = new
GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS").create();
As #matiash noted, you have a non-standard date format that contains microseconds. The problem is that SimpleDateFormat, used by Jackson, incorrectly parses microseconds.
To alleviate this you should create a custom deserializer that truncates the microseconds to milliseconds:
public class MicrosecondDateSerializer extends JsonDeserializer<Date> {
private static SimpleDateFormat formatter =
new SimpleDateFormat("dd-MM-yyyyThh:mm:ss:SSS");
#Override
public Date deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
ObjectCodec oc = jp.getCodec();
JsonNode node = jp.getCodec().readTree(jp);
String dateString = node.get("sent_at").asText();
String dateStringTruncated = dateString.substring(0, dateString.length() - 3);
return formatter.parse(dateStringTruncated);
}
}
I am trying to parse this HTML using jsoup.
My code is:
doc = Jsoup.connect(htmlUrl).timeout(1000 * 1000).get();
Elements items = doc.select("item");
Log.d(TAG, "Items size : " + items.size());
for (Element item : items) {
Log.d(TAG, "in for loop of items");
Element titleElement = item.select("title").first();
mTitle = titleElement.text().toString();
Log.d(TAG, "title is : " + mTitle);
Element linkElement = item.select("link").first();
mLink = linkElement.text().toString();
Log.d(TAG, "link is : " + mLink);
Element descElement = item.select("description").first();
mDesc = descElement.text().toString();
Log.d(TAG, "description is : " + mDesc);
}
I am getting following output:
in for loop of items
D/HtmlParser( 6690): title is : Indonesian president: Some multinationals "take too much"
D/HtmlParser( 6690): link is :
D/HtmlParser( 6690): description is : April 23 - Indonesian President Susilo Bambang Yudhoyono tells a Thomson Reuters Newsmaker event that the country welcomes foreign investment in its resources sector, but must receive a "fair share" of benefits.<div class="feedflare"> <img src="http://feeds.feedburner.com/~ff/reuters/audio/newsmakerus/rss/mp3?d=yIl2AUoC8zA" border="0"></img> <img src="http://feeds.feedburner.com/~ff/reuters/audio/newsmakerus/rss/mp3?i=NX3AY96GfGk:hAtGeOq2ESs:V_sGLiPBpWU" border="0"></img> <img src="http://feeds.feedburner.com/~ff/reuters/audio/newsmakerus/rss/mp3?i=NX3AY96GfGk:hAtGeOq2ESs:F7zBnMyn0Lo" border="0"></img> </div><img src="http://feeds.feedburner.com/~r/reuters/audio/newsmakerus/rss/mp3/~4/NX3AY96GfGk" height="1" width="1"/>
But I want output as:
in for loop of items
D/HtmlParser( 6690): title is : Indonesian president: Some multinationals "take too much"
D/HtmlParser( 6690): link is : http://feeds.reuters.com/~r/reuters/audio/newsmakerus/rss/mp3/~3/KDcQe4gF-3U/62828262.mp3
D/HtmlParser( 6690): description is : April 23 - Indonesian President Susilo Bambang Yudhoyono tells a Thomson Reuters Newsmaker event that the country welcomes foreign investment in its resources sector, but must receive a "fair share" of benefits.
What should I change in my code?
How to achieve my goal. Please help me!!
Thank you in advance!!
There are 2 problems in rss content you fetched.
The link text is not within the <link/> tag but outside of it.
There is some escaped html content within the description tag.
PFB the modified code.
Also I found some clean html content when viewed the URL in Browser, which when parsed will make you easy to extract the desired fields. You can achieve that setting the userAgent as Browser in the Jsoup. But its up to you to decide how to fetch the content.
doc = Jsoup.connect("http://feeds.reuters.com/reuters/audio/newsmakerus/rss/mp3/").timeout(0).get();
System.out.println(doc.html());
System.out.println("================================");
Elements items = doc.select("item");
for (Element item : items) {
Element titleElement = item.select("title").first();
String mTitle = titleElement.text();
System.out.println("title is : " + mTitle);
/*
* The link in the rss is as follows
* <link />http://feeds.reuters.com/~r/reuters/audio/newsmakerus/rss/mp3/~3/NX3AY96GfGk/59621707.mp3
* which doesn't fall in the <link> element but falls under <item> TextNode
*/
String mLink = item.ownText(); //
System.out.println("link is : " + mLink);
Element descElement = item.select("description").first();
/*Unescape the html content, Parse it to a doc, and then fetch only the text leaving behind all the html tags in content
* "/" is a dummy baseURI passed, as we don't care about resolving the links within parsed content.
*/
String mDesc = Parser.parse(Parser.unescapeEntities(descElement.text(), false),"/" ).text();
System.out.println("description is : " + mDesc);
}
I am working on a currency calculator app in android and I am using the open-exchange rate api.I am having problems on how to call the json elements (Currencies),I need a json script that I can use to to display all the currencies and their values. The tricky part is how to get the currency part only.please help.
{
"disclaimer": "Exchange rates provided by [...]",
"license": "Data collected and blended [...]",
"timestamp": 1319730758,
"base": "USD",
"rates": {
"AED": 3.672626,
"AFN": 48.3775,
"ALL": 110.223333,
"AMD": 409.604993,
/* 160 fx rates available - see currencies.json */
"YER": 215.035559,
"ZAR": 8.416205,
"ZMK": 4954.411262,
"ZWL": 322.355011
}
}
Thanks