Getting context from ViewModel in testing - android

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

Related

Changing html properties after fetching API data in android studio

I'm fetching data using API and the one of the data is a HTML formatted text.
The data fetched from the API
{
"id": 4632,
"title": "Soy-and-Ginger-Glazed Salmon with Udon Noodles",
"summary": "Soy-and-Ginger-Glazed Salmon with Udon Noodles might be a good recipe to expand your main course collection. This dairy free and pescatarian recipe serves 4 and costs <b>$5.91 per serving</b>. One serving contains <b>552 calories</b>, <b>48g of protein</b>, and <b>17g of fat</b>. 1 person were impressed by this recipe. From preparation to the plate, this recipe takes roughly <b>1 hour and 35 minutes</b>. This recipe from Food and Wine requires sesame seeds, lime juice, olive oil, and salmon fillets. Taking all factors into account, this recipe <b>earns a spoonacular score of 92%</b>, which is great. If you like this recipe, take a look at these similar recipes: Soy-and-Ginger-Glazed Salmon with Udon Noodles, Soy-and-Ginger-Glazed Salmon with Udon Noodles, and Soy-and-Ginger-Glazed Salmon with Udon Noodles."
}
The summary is a HTML formatted text and im using HTML.fromHtml() to display the displayable styled text. My question is, is it possible to change the properties inside the HTML such as text decoration of a link to another color?
RecipeDetails.java
private final RecipeDetailsListeners recipeDetailsListeners = new RecipeDetailsListeners() {
#SuppressLint("SetTextI18n")
#Override
public void didFetch(RecipeDetailsResponse response, String message) {
Picasso.get().load(response.image).into(recipeImage);
RecipeName.setText(response.title);
recipeSource.setText(response.sourceName);
if (response.sourceName == null){
recipeSource.setText("Unknown");
}
recipeServing.setText(response.servings + " Serving");
recipeTimePrepared.setText(response.readyInMinutes + " Min");
recipeScore.setText(String.valueOf(response.aggregateLikes) + " Likes");
recipeSummary.setText(Html.fromHtml(response.summary, Html.FROM_HTML_MODE_COMPACT));
IngredientListRecipeDetails.setHasFixedSize(true);
IngredientListRecipeDetails.setLayoutManager(new LinearLayoutManager(getBaseContext(), LinearLayoutManager.VERTICAL, false ));
adapter = new recipeDetailsIngredientAdapter(getBaseContext(), response.extendedIngredients);
IngredientListRecipeDetails.setAdapter(adapter);
}
#Override
public void didError(String message) {
customToast("Unsuccessful", message, "Failure");
}
};

Making two API calls with Retrofit to form one object

I'm writing an app which makes unfortunately requires two API calls to complete one object. One call to TMDB to get a list of movies currently in theaters,and then another one to TMDB with the TMDB ID of each movie to get the IMDB ID.
I might also later want to make a third call to OMDB to get the data from there as that's the data we're using on the movie page itself.
I'm new to RXJava and fairly new to Retrofit. I did this the old fashioned way (well, I used OKHTTP) but i'd like to switch to a more elegant version with RXJava and this seems like the perfect use case to me.
Sample First API Call
https://api.themoviedb.org/3/movie/now_playing?api_key={key}&language=en-US&page=1&region=US
JSON response
{
"results":[
{
"vote_count":425,
"id":345940,
"video":false,
"vote_average":6.2,
"title":"The Meg",
"popularity":164.309,
"poster_path":"/xqECHNvzbDL5I3iiOVUkVPJMSbc.jpg",
"original_language":"en",
"original_title":"The Meg",
"genre_ids":[
28,
878,
53,
27
],
"backdrop_path":"/ibKeXahq4JD63z6uWQphqoJLvNw.jpg",
"adult":false,
"overview":"A deep sea submersible pilot revisits his past fears in the Mariana Trench, and accidentally unleashes the seventy foot ancestor of the Great White Shark believed to be extinct.",
"release_date":"2018-08-10"
},
{
"vote_count":1027,
"id":353081,
"video":false,
"vote_average":7.4,
"title":"Mission: Impossible - Fallout",
"popularity":137.095,
"poster_path":"/AkJQpZp9WoNdj7pLYSj1L0RcMMN.jpg",
"original_language":"en",
"original_title":"Mission: Impossible - Fallout",
"genre_ids":[
12,
28,
53
],
"backdrop_path":"/5qxePyMYDisLe8rJiBYX8HKEyv2.jpg",
"adult":false,
"overview":"When an IMF mission ends badly, the world is faced with dire consequences. As Ethan Hunt takes it upon himself to fulfil his original briefing, the CIA begin to question his loyalty and his motives. The IMF team find themselves in a race against time, hunted by assassins while trying to prevent a global catastrophe.",
"release_date":"2018-07-27"
},
{
"vote_count":473,
"id":447200,
"video":false,
"vote_average":6,
"title":"Skyscraper",
"popularity":58.382,
"poster_path":"/5LYSsOPzuP13201qSzMjNxi8FxN.jpg",
"original_language":"en",
"original_title":"Skyscraper",
"genre_ids":[
28,
53,
18
],
"backdrop_path":"/oMKFQmoVgB69fyXfSMu0lGlHJP2.jpg",
"adult":false,
"overview":"Framed and on the run, a former FBI agent must save his family from a blazing fire in the world's tallest building.",
"release_date":"2018-07-13"
},
{
"vote_count":20,
"id":399360,
"video":false,
"vote_average":5.3,
"title":"Alpha",
"popularity":54.434,
"poster_path":"/afdZAIcAQscziqVtsEoh2PwsYTW.jpg",
"original_language":"en",
"original_title":"Alpha",
"genre_ids":[
53,
12,
18
],
"backdrop_path":"/nKMeTdm72LQ756Eq20uTjF1zDXu.jpg",
"adult":false,
"overview":"After a hunting expedition goes awry, a young caveman struggles against the elements to find his way home.",
"release_date":"2018-08-17"
},
{
"vote_count":14,
"id":476292,
"video":false,
"vote_average":4.9,
"title":"Maquia: When the Promised Flower Blooms",
"popularity":47.674,
"poster_path":"/qcnOKCPleLOTWPPgYI0YT1MOQwR.jpg",
"original_language":"ja",
"original_title":"さよならの朝に約束の花をかざろう",
"genre_ids":[
16
],
"backdrop_path":"/cfbjFQ14hSTgXChBEvaEjFiUaKb.jpg",
"adult":false,
"overview":"A story of encounters and partings interwoven between people; this is a human drama with feelings that touch one's heart gradually, which everyone has experienced at least once.",
"release_date":"2018-07-20"
},
{
"vote_count":312,
"id":345887,
"video":false,
"vote_average":6.3,
"title":"The Equalizer 2",
"popularity":41.975,
"poster_path":"/cQvc9N6JiMVKqol3wcYrGshsIdZ.jpg",
"original_language":"en",
"original_title":"The Equalizer 2",
"genre_ids":[
53,
28,
80
],
"backdrop_path":"/z6KLDE72SxE1A8JcJTmmnWArOvR.jpg",
"adult":false,
"overview":"Robert McCall returns to deliver his special brand of vigilante justice -- but how far will he go when it's someone he loves?",
"release_date":"2018-07-20"
},
{
"vote_count":59,
"id":455207,
"video":false,
"vote_average":7.2,
"title":"Crazy Rich Asians",
"popularity":33.287,
"poster_path":"/gnTqi4nhIi1eesT5uYMmhEPGNih.jpg",
"original_language":"en",
"original_title":"Crazy Rich Asians",
"genre_ids":[
35
],
"backdrop_path":"/zeHB7aP46Xs3u4aFLuAq2GFeUGb.jpg",
"adult":false,
"overview":"An American-born Chinese economics professor accompanies her boyfriend to Singapore for his best friend's wedding, only to get thrust into the lives of Asia's rich and famous.",
"release_date":"2018-08-15"
},
{
"vote_count":7,
"id":385448,
"video":false,
"vote_average":5.2,
"title":"The Little Mermaid",
"popularity":29.657,
"poster_path":"/1scpzHhPWDuRc21ci6Tfv5zfKnH.jpg",
"original_language":"en",
"original_title":"The Little Mermaid",
"genre_ids":[
12,
14,
10749,
18
],
"backdrop_path":"/7UY85MIj5IBOGhzL2kNByn7mSBj.jpg",
"adult":false,
"overview":"A young reporter and his niece discover a beautiful and enchanting creature they believe to be the real little mermaid.",
"release_date":"2018-08-17"
},
{
"vote_count":85,
"id":487558,
"video":false,
"vote_average":7.6,
"title":"BlacKkKlansman",
"popularity":29.592,
"poster_path":"/lTgROqb5nrzILPRjUY6JjDIrOhh.jpg",
"original_language":"en",
"original_title":"BlacKkKlansman",
"genre_ids":[
80,
18,
35,
36
],
"backdrop_path":"/gMVdhfQ7q9DFHhDkehrququjGPd.jpg",
"adult":false,
"overview":"Ron Stallworth, an African-American police officer from Colorado, successfully manages to infiltrate the local Ku Klux Klan and become the head of the local chapter.",
"release_date":"2018-08-10"
},
{
"vote_count":394,
"id":400155,
"video":false,
"vote_average":6.9,
"title":"Hotel Transylvania 3: Summer Vacation",
"popularity":29.384,
"poster_path":"/gjAFM4xhA5vyLxxKMz38ujlUfDL.jpg",
"original_language":"en",
"original_title":"Hotel Transylvania 3: Summer Vacation",
"genre_ids":[
10751,
14,
35,
16
],
"backdrop_path":"/m03jul0YdVEOFXEQVUv6pOVQYGL.jpg",
"adult":false,
"overview":"Dracula, Mavis, Johnny and the rest of the Drac Pack take a vacation on a luxury Monster Cruise Ship, where Dracula falls in love with the ship's captain, Ericka, who's secretly a descendant of Abraham Van Helsing, the notorious monster slayer.",
"release_date":"2018-06-30"
},
{
"vote_count":101,
"id":420814,
"video":false,
"vote_average":7.2,
"title":"Christopher Robin",
"popularity":26.982,
"poster_path":"/xR5w0he6czZkcAz459a4iPBqXGe.jpg",
"original_language":"en",
"original_title":"Christopher Robin",
"genre_ids":[
16,
12,
35
],
"backdrop_path":"/uDt8bQ4lGVlabEx5Gl2cPzvy6qz.jpg",
"adult":false,
"overview":"Working-class family man Christopher Robin encounters his childhood friend Winnie-the-Pooh, who helps him to rediscover the joys of life.",
"release_date":"2018-08-03"
},
{
"vote_count":435,
"id":458423,
"video":false,
"vote_average":7.8,
"title":"Mamma Mia! Here We Go Again",
"popularity":25.931,
"poster_path":"/aWicerX4Y7n7tUwRAVHsVcBBpj2.jpg",
"original_language":"en",
"original_title":"Mamma Mia! Here We Go Again",
"genre_ids":[
35,
10749,
10402
],
"backdrop_path":"/8HKwxHZ23sW8wz4yb28IWnAM1M6.jpg",
"adult":false,
"overview":"Five years after meeting her three fathers, Sophie Sheridan prepares to open her mother’s hotel. In 1979, young Donna Sheridan meets the men who each could be Sophie’s biological father.",
"release_date":"2018-07-20"
},
{
"vote_count":101,
"id":454992,
"video":false,
"vote_average":6.4,
"title":"The Spy Who Dumped Me",
"popularity":24.345,
"poster_path":"/2lIr27lBdxCpzYDl6WUHzzD6l6H.jpg",
"original_language":"en",
"original_title":"The Spy Who Dumped Me",
"genre_ids":[
28,
35
],
"backdrop_path":"/9CqzJn0nLaDNM6QWfGkuox2Oi93.jpg",
"adult":false,
"overview":"Audrey and Morgan are best friends who unwittingly become entangled in an international conspiracy when one of the women discovers the boyfriend who dumped her was actually a spy.",
"release_date":"2018-08-03"
},
{
"vote_count":9,
"id":438590,
"video":false,
"vote_average":2.4,
"title":"A.X.L.",
"popularity":23.706,
"poster_path":"/9kB56ZdMB6RgY5QtX9Bar45jCeI.jpg",
"original_language":"en",
"original_title":"A.X.L.",
"genre_ids":[
878
],
"backdrop_path":"/l1nYo0yzKjf84atnBDbx0do16vQ.jpg",
"adult":false,
"overview":"The life of a teenage boy is forever altered by a chance encounter with cutting edge military technology.",
"release_date":"2018-08-24"
},
{
"vote_count":184,
"id":445651,
"video":false,
"vote_average":6.8,
"title":"The Darkest Minds",
"popularity":20.9,
"poster_path":"/94RaS52zmsqaiAe1TG20pdbJCZr.jpg",
"original_language":"en",
"original_title":"The Darkest Minds",
"genre_ids":[
878,
53
],
"backdrop_path":"/5BxrMNGl3YDiWgHCVJu8iLQoJDM.jpg",
"adult":false,
"overview":"After a disease kills 98% of America's children, the surviving 2% develop superpowers and are placed in internment camps. A 16-year-old girl escapes her camp and joins a group of other teens on the run from the government.",
"release_date":"2018-08-03"
},
{
"vote_count":5,
"id":489999,
"video":false,
"vote_average":5.2,
"title":"Searching",
"popularity":20.762,
"poster_path":"/9N0T3BaHZNdUCcMZQIM3yMUFwEh.jpg",
"original_language":"en",
"original_title":"Searching",
"genre_ids":[
18,
53
],
"backdrop_path":"/1q5AauYD1szopz5qnd6qqxnpTHG.jpg",
"adult":false,
"overview":"After his 16-year-old daughter goes missing, a desperate father breaks into her laptop to look for clues to find her. A thriller that unfolds entirely on computer screens.",
"release_date":"2018-08-24"
},
{
"vote_count":20,
"id":347375,
"video":false,
"vote_average":5.1,
"title":"Mile 22",
"popularity":19.505,
"poster_path":"/2L8ehd95eSW9x7KINYtZmRkAlrZ.jpg",
"original_language":"en",
"original_title":"Mile 22",
"genre_ids":[
28
],
"backdrop_path":"/wWoCid7YUxiLhq3ZZT6CtFEDPXw.jpg",
"adult":false,
"overview":"A CIA field officer and an Indonesian police officer are forced to work together in confronting political corruption. An informant must be moved twenty-two miles to safety.",
"release_date":"2018-08-17"
},
{
"vote_count":28,
"id":439015,
"video":false,
"vote_average":4.3,
"title":"Slender Man",
"popularity":18.529,
"poster_path":"/huSncs4RyvQDBmHjBBYHSBYJbSJ.jpg",
"original_language":"en",
"original_title":"Slender Man",
"genre_ids":[
27
],
"backdrop_path":"/5K0fgMaJSdEvqSsS8e3Ez4TpvXR.jpg",
"adult":false,
"overview":"In a small town in Massachusetts, four high school girls perform a ritual in an attempt to debunk the lore of Slender Man. When one of the girls goes mysteriously missing, they begin to suspect that she is, in fact, his latest victim.",
"release_date":"2018-08-10"
},
{
"vote_count":1,
"id":456086,
"video":false,
"vote_average":0,
"title":"Support the Girls",
"popularity":17.759,
"poster_path":"/leS393QLCe9UyY9TuWT8OvwuNk1.jpg",
"original_language":"en",
"original_title":"Support the Girls",
"genre_ids":[
18
],
"backdrop_path":"/wMiJPxdZ4avOtqijP62T6yR1wqo.jpg",
"adult":false,
"overview":"Lisa Conroy may not love managing the restaurant Double Whammies, but she loves her employees more than anything, not only Danyelle, and Maci, her closest friends, but also her extended family. Unfortunately, the cheap, curmudgeonly owner Ben Cubby doesn’t care nearly as much, and confronts Lisa when he learns that she’s using the restaurant to raise money for Shaina, an employee in legal trouble related to an abusive boyfriend. To get even, the girls decide to sabotage the restaurant on the night of a major mixed martial arts fight.",
"release_date":"2018-08-24"
},
{
"vote_count":0,
"id":450484,
"video":false,
"vote_average":0,
"title":"An L.A. Minute",
"popularity":17.665,
"poster_path":"/aI2CN1QloY8ZWdeNJac7EQjeHkt.jpg",
"original_language":"en",
"original_title":"An L.A. Minute",
"genre_ids":[
],
"backdrop_path":null,
"adult":false,
"overview":"Best-selling author Ted Gold faces a moral dilemma when Velocity, an avant-garde performance artist and the living embodiment of integrity, rocks his 1% world.",
"release_date":"2018-08-24"
}
],
"page":1,
"total_results":124,
"dates":{
"maximum":"2018-08-29",
"minimum":"2018-07-12"
},
"total_pages":7
}
Sample second API call to get the IMDB id
https://api.themoviedb.org/3/movie/345940?api_key={api_key}&language=en-US
JSON response
{
"adult":false,
"backdrop_path":"/ibKeXahq4JD63z6uWQphqoJLvNw.jpg",
"belongs_to_collection":null,
"budget":150000000,
"genres":[
{
"id":28,
"name":"Action"
},
{
"id":878,
"name":"Science Fiction"
},
{
"id":53,
"name":"Thriller"
},
{
"id":27,
"name":"Horror"
}
],
"homepage":"http://www.themeg.movie",
"id":345940,
"imdb_id":"tt4779682",
"original_language":"en",
"original_title":"The Meg",
"overview":"A deep sea submersible pilot revisits his past fears in the Mariana Trench, and accidentally unleashes the seventy foot ancestor of the Great White Shark believed to be extinct.",
"popularity":164.309,
"poster_path":"/xqECHNvzbDL5I3iiOVUkVPJMSbc.jpg",
"production_companies":[
{
"id":56241,
"logo_path":null,
"name":"Maeday Productions",
"origin_country":""
},
{
"id":56242,
"logo_path":"/1YORRYmg7hgYIgoJek8jU3cykuQ.png",
"name":"Apelles Entertainment",
"origin_country":"US"
},
{
"id":48778,
"logo_path":"/tto2UKph873Xh1ytxfNBgCxT8NO.png",
"name":"Gravity Pictures",
"origin_country":"CN"
},
{
"id":435,
"logo_path":null,
"name":"Di Bonaventura Pictures",
"origin_country":"US"
},
{
"id":107790,
"logo_path":null,
"name":"Flagship Entertainment Group",
"origin_country":"CN"
}
],
"production_countries":[
{
"iso_3166_1":"CN",
"name":"China"
},
{
"iso_3166_1":"US",
"name":"United States of America"
}
],
"release_date":"2018-08-09",
"revenue":141500000,
"runtime":113,
"spoken_languages":[
{
"iso_639_1":"en",
"name":"English"
}
],
"status":"Released",
"tagline":"Chomp On This",
"title":"The Meg",
"video":false,
"vote_average":6.2,
"vote_count":426
}
Movie object
package watch.trigger.Model;
import com.google.gson.annotations.SerializedName;
/**
* Created by paxie on 10/7/17.
*/
public class Movie {
private String imdbID;
#SerializedName("Title")
private String title;
#SerializedName("Year")
private String year;
private String summary;
private String mpaaRating;
private double imdbRating;
#SerializedName("Poster")
private String posterURL;
private String award;
public Movie(String imdbID, String title, String year, String posterURL, String award) {
this.imdbID = imdbID;
this.title = title;
this.year = year;
this.posterURL = posterURL;
this.award = award;
}
public Movie(String imdbID) {
this.imdbID = imdbID;
}
public Movie(String imdbID, String title) {
this.imdbID = imdbID;
this.title = title;
}
public Movie() {
}
public String getImdbID() {
return imdbID;
}
public void setImdbID(String imdbID) {
this.imdbID = imdbID;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getYear() {
return year;
}
public void setYear(String year) {
this.year = year;
}
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public String getMpaaRating() {
return mpaaRating;
}
public void setMpaaRating(String mpaaRating) {
this.mpaaRating = mpaaRating;
}
public double getImdbRating() {
return imdbRating;
}
public void setImdbRating(double imdbRating) {
this.imdbRating = imdbRating;
}
public String getPosterURL() {
return posterURL;
}
public void setPosterURL(String posterURL) {
this.posterURL = posterURL;
}
public String getAward() {
return award;
}
public void setAward(String award) {
this.award = award;
}
}
Do a combineLatest on the three network calls and wrap them in an object, then in subscribe pull the values out into your final object and send it to your presenter or display or other business logic
Observable.combineLatest(
networkCallOne().take(1),
networkCallTwo().take(1),
networkCallThree().take(1),
(obj1, obj2, obj3) -> new WrapperObject(obj1, obj2, obj3))
.observeOn(Schedulers.io())
.take(1)
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(wrapperObj -> {
//do some logic
})
For combineLatest
when an item is emitted by any of the Observables, combine the
latest item emitted by each Observable via a specified function and
emit items based on the results of this function
This will wait until all 3 network calls return then combine the latest values
And take(1) will just ensure you only get 1 value. Be sure to handle errors as well as this does not do that for you

Retrofit JSON parsing issues in retrieving value from list ? How to solve?

I have A NESTED JSON to parse, for instance ;
[
{
"ID": {
"Tag": "string",
"TypeCode": 5,
"Value": "68613",
"IsBinaryUnique": true
},
"NATIVE_DATE": {
"Tag": "string",
"TypeCode": 5,
"Value": "2015/02/22",
"IsBinaryUnique": true
},
"ANNOUNCEMENT_DATE": {
"Tag": "string",
"TypeCode": 5,
"Value": "February 22, 2015",
"IsBinaryUnique": true
},
"EXPIRY": {
"Tag": "string",
"TypeCode": 5,
"Value": "",
"IsBinaryUnique": true
},
"ANNOUNCEMENT_DESCRIPTION": {
"Tag": "string",
"TypeCode": 5,
"Value": "",
"IsBinaryUnique": true
},
"ANNOUNCEMENT_TITLE": {
"Tag": "string",
"TypeCode": 5,
"Value": "Emirates Motor Company unveils all-new Mercedes-Benz 2015 C-Class",
"IsBinaryUnique": true
},
"ANNOUNCEMENT_IMAGE": {
"Tag": "string",
"TypeCode": 5,
"Value": "HTTP://94.56.199.34/EMC/EMCPortal/DesktopModules/Farabi.ICatalog/CatalogImages/488/C-2048_sd-eng.jpg",
"IsBinaryUnique": true
},
"ANNOUNCEMENT_IMAGE_THUMBNAIL": {
"Tag": "string",
"TypeCode": 5,
"Value": "http://94.56.199.34/EMC/IPDP/thumbnail.ashx?File=/DesktopModules/Farabi.ICatalog/CatalogImages/488/C-2048_sd-eng.jpg",
"IsBinaryUnique": true
},
"ANNOUNCEMENT_HTML": {
"Tag": "string",
"TypeCode": 5,
"Value": "<!--NEWS-->\r\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\r\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n<head>\r\n <meta name=\"viewport\" content=\"width=device-width\" />\r\n <title>News & Promotions</title>\r\n <style type=\"text/css\">\r\n H1\r\n {\r\n text-align: left;\r\n color:Black;\r\n font-size:22px;\r\n font-weight: bold;\r\n font-family:Arial;\r\n }\r\n Body\r\n {\r\n background-color: transparent\";\r\n font-family:Arial;\r\n }\r\n .Header\r\n {\r\n -webkit-border-top-left-radius: 10px;\r\n -webkit-border-bottom-left-radius: 10px;\r\n -moz-border-radius-topleft: 10px;\r\n -moz-border-radius-bottomleft: 10px;\r\n border-top-left-radius: 10px;\r\n border-bottom-left-radius: 10px;\r\n background-color: #0e100f\";\r\n margin-top: 10px;\r\n font-weight: bold;\r\n border: 5 none transperant;\r\n font-family:Arial;\r\n }\r\n .SubTitle\r\n {\r\n color: black;\r\n font-weight: bold;\r\n font-size:16px;\r\n font-family:Arial;\r\n }\r\n \r\n .ContentText\r\n {\r\n color: black;\r\n font-size:16px;\r\n font-family:Arial;\r\n }\r\n \r\n .Content\r\n {\r\n margin-left: 5px;\r\n }\r\n </style>\r\n</head>\r\n<body leftmargin=\"0\" topmargin=\"0\">\r\n <table border=\"0\" cellpadding=\"5\" cellspacing=\"5\" >\r\n <tr>\r\n <td>\r\n <h1>\r\n Emirates Motor Company unveils all-new Mercedes-Benz 2015 C-Class\r\n </h1>\r\n </td>\r\n </tr>\r\n <tr class=\"SubTitle\">\r\n <td align=\"right\">\r\n February 22, 2015\r\n </td>\r\n </tr>\r\n <tr class=\"SubTitle\">\r\n <td align=\"right\">\r\n Valid Till &nbsp $Expired_Date\r\n </td>\r\n </tr>\r\n <tr>\r\n <td>\r\n <img alt=\"\" src=\"http://94.56.199.34/EMC/EMCPortal/DesktopModules/Farabi.ICatalog/CatalogImages/488/C-2048_sd-eng.jpg\" style=\"width: 100%; float: right\" hspace=\"0\" />\r\n </td>\r\n </tr>\r\n <tr>\r\n <td> \r\n <div class=\"Content\" valign=\"top\">\r\n <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\r\n <tr>\r\n <td class=\"ContentText\" align=\"left\">\r\n <p><span>Emirates Motor Company (EMC), General Distributors of Mercedes-Benz in the Emirate of Abu Dhabi and the flagship company of Al Fahim Group, launched the all-new Mercedes-Benz 2015 C-Class in a gala iftar and a superb unveiling of the fabulous new innovative car on Saturday, 5 July at their close-to-heart Airport Road Showroom in Abu Dhabi.</span></p>\r\n<p><span>In the presence of newly appointed CEO Automotive of Al Fahim Group, Mr. Frank Bernthaler, the celebrative evening continued with a press conference where EMC hosts Mr. Kamal Rafih, General Manager, Mr. Jordan Duckett, General Sales Manager, and Mr. Rabih Eid, Operations Manager, were head-table spokespersons.</span></p>\r\n<p><span>\"We are delighted to be revealing the admirable all-new Mercedes-Benz 2015 C-Class during a blessed, festive month and announce the great achievements we've accomplished so far this year,\" praised Mr. Rafih in his speech to the media. \"As we conclude the first half of the year, we also celebrate a well-earned increase in our sales performance of 42% compared to the same period last year,\" he added.</span></p>\r\n<p><span>Among the most popular models in 2014 which witnessed an exponential rise were the legendary Mercedes-Benz S-Class by an impressive 347%, the sporty A-Class by 156%, the luxurious E-Class by 46%, and the entire sports utility vehicle (SUV) range by 22%, which includes the G-Class, GL-Class, GLK Class and the M-Class.</span></p>\r\n<p><span>During the memorable occasion, media representatives and guests were also invited to explore the latest innovation by Mercedes-Benz and register for the driving experience. The all-new C-Class sets new standards in the premium medium-size category in terms of striking appearance, cutting-edge technology, spacious comfort and refined sportiness. A host of new assistance systems offers safety of the highest standard, while a new optional air-sprung suspension provides for exemplary ride and driving comfort as well as nimble and agile handling.</span></p>\r\n<p><span>Thanks to intelligent and innovative lightweight construction, the aluminum hybrid body is around 70 kilograms lighter than a conventional steel body. Compared with the successful predecessor, the aluminum content has increased from less than 10% to almost 50%. As a result, the vehicle's overall weight is reduced by up to 100 kilograms. Furthermore, with an 80-millimeter increase in the wheelbase compared with the previous model, the vehicle is 95 millimeters longer and 40 millimeters wider. The result is a more spacious interior.</span></p>\r\n<p><strong><span>High-class interior with fine details</span></strong><span><br />\r\nThe innovative touchpad developed by Mercedes-Benz in the hand-rest marks a further evolutionary step. As on a smartphone, this provides for simple and intuitive operation of all the head-unit functions using finger gestures. The touchpad also permits letters, numbers and special characters to be entered in handwriting - in any language supported by Audio 20. One of the main highlights of the innovative touchpad is that Arabic letters, numbers and even special characters are supported, and can be entered into the handwriting recognition function.</span></p>\r\n<p><strong><span>Mercedes-Benz Intelligent Drive: the intelligent car</span></strong><span><br />\r\nThe new C-Class incorporates almost all of the new assistance systems with a host of enhanced functions which celebrated their world premiere in the S-Class and E-Class only some months ago. The assistance systems enhance both comfort and safety. Mercedes-Benz calls this Intelligent Drive.</span></p>\r\n<p><span>The new C-Class offers numerous innovative safety and assistance systems. It is equipped as standard with ATTENTION ASSIST, which can warn the driver of inattentiveness and fatigue. In addition to Adaptive Brake Assist, which offers protection from collisions from speeds as low as 7 km/h, standard-fit COLLISION PREVENTION ASSIST PLUS also features an additional function: when the risk of collision persists and the driver fails to respond, the system is able to carry out autonomous braking at speeds of up to 200 km/h, thereby reducing the severity of collisions with slower or stopping vehicles. The system also brakes in response to stationary vehicles at a speed of up to 50 km/h, and is able to prevent rear-end collisions at up to 40 km/h.</span></p>\r\n<p><strong><span>Other safety features include:</span></strong> <span><br />\r\n-DISTRONIC PLUS with Steering Assist and integrated Stop&Go Pilot\r\n<br />\r\n-BAS PLUS Brake Assist and PRE-SAFE® Brake\r\n<br />\r\n-Enhanced Active Lane Keeping Assist\r\n<br />\r\n-Active Parking Assist\r\n<br />\r\n-Traffic Sign Assist\r\n<br />\r\n-Adaptive Highbeam Assist Plus</span></p>\r\n </td>\r\n </tr>\r\n </table>\r\n </div>\r\n </td>\r\n </tr>\r\n </table>\r\n</body>\r\n</html>\r\n",
"IsBinaryUnique": true
}
},
{
"ID": {
"Tag": "string",
"TypeCode": 5,
"Value": "66055",
"IsBinaryUnique": true
}, etc....}]
I need to get the announcement title values, in order to do this I have created a model class for Announcement Title.
public class AnnouncementTitle {
#SerializedName("Tag")
private String tag;
#SerializedName("TypeCode")
private String typecode;
#SerializedName("Value")
private String value;
#SerializedName("IsBinaryUnique")
private boolean isbinary;
public AnnouncementTitle(String tag, String typecode, String value, boolean isbinary) {
this.tag = tag;
this.typecode = typecode;
this.value = value;
this.isbinary = isbinary;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public String getTypecode() {
return typecode;
}
public void setTypecode(String typecode) {
this.typecode = typecode;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public boolean isIsbinary() {
return isbinary;
}
public void setIsbinary(boolean isbinary) {
this.isbinary = isbinary;
}
}
and my API class is like,
public interface Api {
String BASE_URL ="base url";
#GET("url to get values from")
Call<ArrayList<AnnouncementTitle>> getData();}
I have implemented the retrofit call in MainActivity.java
public void getData() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Api.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
Api api = retrofit.create(Api.class);
Call<ArrayList<AnnouncementTitle>> call = api.getData();
call.enqueue(new Callback<ArrayList<AnnouncementTitle>>() {
#Override
public void onResponse(Call<ArrayList<AnnouncementTitle>> call, Response<ArrayList<AnnouncementTitle>> response) {
ArrayList<AnnouncementTitle> response_array = response.body();
Log.e("Response "," "+ response_array);
Log.e("Response "," "+ response_array.size());
Log.e("Response ","Value "+ response_array.get(0).getValue());
for (int i = 0;i<response_array.size();i++){
AnnouncementTitle announcementTitle= response_array.get(i);
String a = announcementTitle.getTag();
String b = announcementTitle.getValue();
String c = announcementTitle.getTypecode();
//Log.e("Response ","Value "+ b);
// Log.e("Response ","Value "+ c);
}
}
#Override
public void onFailure(Call<ArrayList<AnnouncementTitle>> call, Throwable t) {
Log.e("Failed "," ");
}
});
}}
My problem is I get the response as array list correctly, but the values inside ArrayList are null for instance from the above code the string values a,b,c, all of them returning value as null.Can anyone help to find and resolve this problem?.
First: JSON you are showing is invalid. Apart from invalid braces placement if you declare
#SerializedName("TypeCode")
private String typecode;
you will have
"TypeCode": "5"
instead of
"TypeCode": 5
in JSON. The correct JSON representing your an ArrayList<AnnouncementTitle> is:
[
{"ID": {
"Tag": "string",
"TypeCode": "5",
"Value": "68613",
"IsBinaryUnique": true}
},
{"NATIVE_DATE": {
"Tag": "string",
"TypeCode": "5",
"Value": "2015/02/22",
"IsBinaryUnique": true}
},
{"ANNOUNCEMENT_TITLE": {
"Tag": "string",
"TypeCode": "5",
"Value": "Title of announcement",
"IsBinaryUnique": true}
}
]
Second: Your request and response have the same structure - ArrayList<AnnouncementTitle>. You are sending this list and getiing it back as an server answer. Is it really the thing you want to do?
Third: If you really want ArrayList<AnnouncementTitle> as an server answer why do you parse it by hand with
for (int i = 0;i<response_array.size();i++){
...
}
? It would be better to force Retrofit do that for you with:
call.enqueue(new Callback<ArrayList<AnnouncementTitle>>() {
#Override
public void onResponse(Call<ArrayList<AnnouncementTitle>> call, ArrayList<AnnouncementTitle> list) {
ArrayList<AnnouncementTitle> response_list = list;
}
Get JSON object from list like this
JSONObject obj = responseArray.get(i);
JSONObject ID = obj.getJSonObject("ID");
Variables in your model class should be like this (I think you forgot to set
TypeCode to declare Integer)
#SerializedName("Tag")
private String tag;
#SerializedName("TypeCode")
private int typecode;
#SerializedName("Value")
private String value;
#SerializedName("IsBinaryUnique")
private boolean isbinary;
Pass the data in to model class like this in for loop
AnnouncementTitle model = new AnnouncementTitle(
ID.getString("TAG"),
ID.getInt("TypeCode"),
ID.getString("Value"),
ID.getBoolean("IsBinaryUnique")
);
copy your all json response and change it to pojo class from the link
https://www.jsonutils.com/
and make the get set method in class
your interface will become like that
public interface Api {
#GET("url to get values from")
Call<PojoClassName> getData();
}
retrofit class look like that
Api api = retrofit.create(Api.class);
Call<PojoClassName> call = api.getData();
call.enqueue(new Callback<PojoClassName>() {
#Override
public void onResponse(Call<PojoClassName> call, Response<PojoClassName> response) {
Log.e("Response "," "+response.body().toString);
Log.e("Response "," "+response.body().getID().getTag());
Log.e("Response "," "+response.body().getEXPIRY().getTag());
}
#Override
public void onFailure(Call<PojoClassName> call, Throwable t) {
Log.e("Failed ",t.getMessage());
}
});

How to fix inaccurate DateTime (minutes) parsed with Jackson/Gson libraries?

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);
}
}

Tutorial on onpen_exchange rate

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

Categories

Resources