Can't display data on recyclerView - android

This app is supposed to display movie's tittles fetched from an API into a RecyclerView. I know I am getting the data right because of logs I made on the movies Arraylist, but for some reason, I can't display the info. The app does not crash, it just shows an empty view. I do really appreciate your help.
Disclaimers: I am a newbie, and this solution might be quite simple for experienced people. I usually don't ask questions unless I can't solve the issue, actually this is my first question ever. I've been around this for a few days now and I can't find a way. I understand that this code might have more than one problem on it, and you are very welcome to point them all out.
SO, this is my main activity
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
public static final String LOG_TAG = MainActivity.class.getSimpleName();
private static final String MOST_POPULAR_MOVIES = "http://api.themoviedb.org/3/discover/movie?sort_by=popularity.desc&api_key=XXXXXXXXXXXXXXXXXXX";
ArrayList<Pelicula> ArrayDePeliculas;
private RecyclerView mPelisList;
private AdapterRV adapterRV;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PeliculasAsyncTask task = new PeliculasAsyncTask();
task.execute(createUrl(MOST_POPULAR_MOVIES));
adapterRV = new AdapterRV(getApplicationContext(),/*Aca puede faltar algo*/ new ArrayList<Pelicula>());
mPelisList = findViewById(R.id.rv_pelis);
GridLayoutManager layoutManager = new GridLayoutManager(this, 2);
mPelisList.setLayoutManager(layoutManager);
mPelisList.setAdapter(adapterRV);
}
public void updateUi(ArrayList<Pelicula> peliculas) {
}
/**
* Returns new URL object from the given string URL.
*/
private URL createUrl(String stringUrl) {
URL url = null;
try {
url = new URL(stringUrl);
} catch (MalformedURLException exception) {
Log.e(LOG_TAG, "Error with creating URL", exception);
return null;
}
return url;
}
/**
* Make an HTTP request to the given URL and return a String as the response.
*/
private String makeHttpRequest(URL url) throws IOException {
String jsonResponse = "";
// If the URL is null, then return early.
if (url == null) {
return jsonResponse;
}
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setReadTimeout(10000 /* milliseconds */);
urlConnection.setConnectTimeout(15000 /* milliseconds */);
urlConnection.connect();
// If the request was successful (response code 200),
// then read the input stream and parse the response.
if (urlConnection.getResponseCode() == 200) {
inputStream = urlConnection.getInputStream();
jsonResponse = readFromStream(inputStream);
} else {
Log.e(LOG_TAG, "Error response code: " + urlConnection.getResponseCode());
}
} catch (IOException e) {
Log.e(LOG_TAG, "Problem retrieving the earthquake JSON results.", e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (inputStream != null) {
// function must handle java.io.IOException here
inputStream.close();
}
}
return jsonResponse;
}
/**
* Convert the {#link InputStream} into a String which contains the
* whole JSON response from the server.
*/
private String readFromStream(InputStream inputStream) throws IOException {
StringBuilder output = new StringBuilder();
if (inputStream != null) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
BufferedReader reader = new BufferedReader(inputStreamReader);
String line = reader.readLine();
while (line != null) {
output.append(line);
line = reader.readLine();
}
}
return output.toString();
}
/**
* TODO modificar la url que le estas pasando
*/
public ArrayList<Pelicula> extractFeatureFromJson(String jsonResponse) {
ArrayList<Pelicula> arraydePelis = new ArrayList<>();
try {
JSONObject baseJsonResponse = new JSONObject(jsonResponse);
JSONArray resultsArray = baseJsonResponse.getJSONArray("results");
for (int i = 0; i < resultsArray.length(); i++) {
// If there are results in the features array
if (resultsArray.length() > 0) {
// Extract out the first feature (which is an earthquake)
JSONObject firstResult = resultsArray.getJSONObject(i);
String tittle = firstResult.getString("title");
Pelicula pelicula = new Pelicula(tittle);
arraydePelis.add(pelicula);
}
}
} catch (JSONException e) {
Log.e(LOG_TAG, "Problem parsing the earthquake JSON results", e);
}
return arraydePelis;
}
private class PeliculasAsyncTask extends AsyncTask<URL, Void, ArrayList<Pelicula>> {
#Override
protected ArrayList<Pelicula> doInBackground(URL... urls) {
// Create URL object
URL url = createUrl(MOST_POPULAR_MOVIES);
// Perform HTTP request to the URL and receive a JSON response back
String jsonResponse = "";
try {
jsonResponse = makeHttpRequest(url);
} catch (IOException e) {
Log.e(LOG_TAG, "Problem making the HTTP request.", e);
}
// Extract relevant fields from the JSON response and create an {#link Event} object
ArrayList<Pelicula> ArrayPeliculas = extractFeatureFromJson(jsonResponse);
// Return the {#link Event} object as the result fo the {#link TsunamiAsyncTask}
return ArrayPeliculas;
}
#Override
protected void onPostExecute(ArrayList<Pelicula> data) {
if (data == null) {
return;
}
adapterRV.notifyDataSetChanged();
mPelisList.setAdapter(adapterRV);
Log.e("Nada", data.get(6).getTittle());
super.onPostExecute(data);
}
}
}
The Movie class
public class Pelicula {
//Fields
private String mTittle;
//Constructor
public Pelicula(String Tittle){
mTittle= Tittle;
}
//Methods
public String getTittle (){
return mTittle;
}
}
And finally, the recyclerView adapter
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class AdapterRV extends RecyclerView.Adapter<AdapterRV.PelisViewHolder> {
//Fields
List<Pelicula> mPeliculas;
private Context context;
/* TODO, comprobar que no necesitas esto: mNumberItems = numberOfItems; y poner autofit en grid view */
//Constructor
public AdapterRV (Context context, ArrayList<Pelicula> peliculas){
mPeliculas = peliculas;
this.context= context;
}
//Metodos
#NonNull
#Override
public PelisViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
Context context = parent.getContext();
int layoutForListItem = R.layout.item_layout;
LayoutInflater inflater= LayoutInflater.from(context);
View view = inflater.inflate(layoutForListItem, parent, false);
PelisViewHolder viewHolder = new PelisViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull PelisViewHolder holder, int position) {
Pelicula peliculas = mPeliculas.get(position);
TextView textView = holder.listItemTittleView;
textView.setText(peliculas.getTittle());
}
#Override
public int getItemCount() {
return mPeliculas.size();
}
public class PelisViewHolder extends RecyclerView.ViewHolder{
TextView listItemTittleView;
public PelisViewHolder(#NonNull View itemView) {
super(itemView);
listItemTittleView = itemView.findViewById(R.id.tv_title);
}
}
}

The problem is that you are passing new ArrayList<Pelicula>() to your adapter, and this list is remaining empty. I suggest you declare a global reference of Pelicula list inside your MainActivity and then pass it to the adapter. Whenever that list changes, then notifyDataSetChanged.
If you don't want to declare a global reference, just declare a method inside your adapter:
public void setList(ArrayList list){
this.list = list;
}
and in your MainActivity, just everything you get a new list, setList(newPeliculaList) and adapterRV.notifyDataSetChanged()
Edit:
in onCreate() before declaring the AdapterRV:
just put this:
ArrayDePeliculas = new ArrayList<Pelicula>();

Do you see these 2 lines in onCreate()
adapterRV = new AdapterRV(getApplicationContext(),new ArrayList<Pelicula>());
...
...
mPelisList.setAdapter(adapterRV);
Move them to onPostExecute() of the asyncTask and pass the data instead of a new ArrayList<Pelicula>():
#Override
protected void onPostExecute(ArrayList<Pelicula> data) {
//assuming the list is full and all is good
if (data == null) {
return;
}
//here...
adapterRV = new AdapterRV(getApplicationContext(),data);
mPelisList.setAdapter(adapterRV);
Log.e("Nada", data.get(6).getTittle());
super.onPostExecute(data);
}
UPDATE:
Its because you don't initialize the list in the adapter:
public class AdapterRV extends RecyclerView.Adapter<AdapterRV.PelisViewHolder> {
//Fields
//here you must initialize like this:
List<Pelicula> mPeliculas = new ArrayList<Pelicula>();
.....

Related

How to get and display arraylist results from asynctask in onCreate method

I'm working on udacity popular movies stage 1 project that will allow me to discover movies from themoviedb database.
I've created Movie, MovieAdapter, and MainActivity(with FetchMovieAsyncTask as inner class) classes. But I keep getting below error
java.lang.NullPointerException: Attempt to invoke interface method
'int java.util.List.size()' on a null object reference
These are my codes
Movie class:
public class Movie{
private String mMovieTitle;
private String mPosterPath;
private String mOverview;
private String mReleaseDate;
private double mRating;
public Movie(){
mMovieTitle = null;
mPosterPath = null;
mOverview = null;
mReleaseDate = null;
mRating = -1.0;
}
public Movie(String title){
mMovieTitle = title;
}
public Movie(String title, String posterPath, String overview, String releaseDate, double rating){
mMovieTitle = title;
mPosterPath = posterPath;
mOverview = overview;
mReleaseDate = releaseDate;
mRating = rating;
}
public String getMovieTitle(){
return mMovieTitle;
}
public String getPosterPath(){
return mPosterPath;
}
public String getOverview(){
return mOverview;
}
public String getReleaseData(){
return mReleaseDate;
}
public double getRating(){
return mRating;
}
}
MovieAdapter class:
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
/**
* Created by ibayp on 04/08/2017.
*/
public class MovieAdapter extends ArrayAdapter<Movie> {
Context context;
ArrayList<Movie> movies;
public MovieAdapter(Context context, ArrayList<Movie> movies){
super(context, 0, movies);
this.context = context;
this.movies = movies;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View view = convertView;
if(view == null){
view = LayoutInflater.from(getContext()).inflate(R.layout.poster_list, parent, false);
}
ImageView imageView = (ImageView)view.findViewById(R.id.movie_poster);
Picasso.with(getContext())
.load("https://image.tmdb.org/t/p/w500/kqjL17yufvn9OVLyXYpvtyrFfak.jpg")
.into(imageView);
return view;
}
}
and MainActivity class:
package com.android.ibayp.popularmovies;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
GridView gridView;
ArrayList<Movie> movies;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new FetchMovieAsyncTask().execute("popularity.desc");
MovieAdapter adapter = new MovieAdapter(this, movies);
gridView = (GridView)findViewById(R.id.grid_view);
gridView.setAdapter(adapter);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long l) {
Movie movie = (Movie)parent.getItemAtPosition(position);
Intent intent = new Intent(MainActivity.this, DetailActivity.class);
intent.putExtra("title", movie.getMovieTitle());
startActivity(intent);
}
});
}
private class FetchMovieAsyncTask extends AsyncTask<String, Void, ArrayList<Movie>> {
private final String TAG = com.android.ibayp.popularmovies.FetchMovieAsyncTask.class.getSimpleName();
private static final String API_KEY = "api key";
private static final String BASE_URL = "https://api.themoviedb.org/3/discover/movie?";
private String API_PARAM = "api_key";
private String SORT_BY = "sort_by";
public URL buildURL(String[] sortMethod){
Uri builtUri = Uri.parse(BASE_URL).buildUpon()
.appendQueryParameter(API_PARAM, API_KEY)
.appendQueryParameter(SORT_BY, sortMethod[0])
.build();
URL url = null;
try{
url = new URL(builtUri.toString());
}catch (MalformedURLException e){
e.printStackTrace();
}
Log.v(TAG, "BUILT URI: " +url);
return url;
}
private String makeHttpRequst(URL url)throws IOException {
String jsonResponse = "";
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
try{
urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
inputStream = urlConnection.getInputStream();
jsonResponse = readStream(inputStream);
}catch (IOException e){
e.printStackTrace();
}finally {
if(urlConnection!=null){
urlConnection.disconnect();
}
if (inputStream!=null){
inputStream.close();
}
}
return jsonResponse;
}
private String readStream(InputStream inputStream) throws IOException{
StringBuilder results = new StringBuilder();
if(inputStream!=null){
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
BufferedReader reader = new BufferedReader(inputStreamReader);
String line = reader.readLine();
while (line!=null){
results.append(line);
line = reader.readLine();
}
}
return results.toString();
}
private ArrayList<Movie> getMovieFromJson(String movieJson){
movies = new ArrayList<Movie>();
try{
JSONObject baseResponse = new JSONObject(movieJson);
JSONArray resultsArray = baseResponse.getJSONArray("results");
Log.v(TAG, "Array Results: "+resultsArray.length());
if (resultsArray.length() > 0){
for (int i = 0; i<resultsArray.length(); i++ ){
JSONObject movieInformation = resultsArray.getJSONObject(i);
movies.add(new Movie(movieInformation.getString("title"),
movieInformation.getString("poster_path"),
movieInformation.getString("overview"),
movieInformation.getString("release_date"),
movieInformation.getDouble("vote_average")));
}
}
}catch (JSONException e){
Log.v(TAG, "Problem parsing Json" + e);
}
return movies;
}
#Override
protected ArrayList<Movie> doInBackground(String... strings) {
URL url = buildURL(strings);
String jsonResponse = "";
try{
jsonResponse = makeHttpRequst(url);
}catch (IOException e){
Log.v(TAG, "IO Exception error "+e);
}
movies = getMovieFromJson(jsonResponse);
return movies;
}
#Override
protected void onPostExecute(ArrayList<Movie> movies) {
if (movies==null){
return;
}
super.onPostExecute(movies);
}
}
}
I used logging and managed to get the correct json results, but I can't display it on the ui thread.
How can I solve this? Thanks
*note that I used dummy image for the poster
When you instantiate your adapter movies are null. Because asynctask is running in parallel thread. Instantiate your adapter in your asynctask's onPostExecute method. This way you will be sure asynctask is completed.
#Override
protected void onPostExecute(ArrayList<Movie> movies) {
if (movies==null){
return;
}
super.onPostExecute(movies);
MovieAdapter adapter = new MovieAdapter(MainActivity.this, movies);
gridView.setAdapter(adapter);
}
Call adapter.notifyDataSetChanged() after movies.add(...) or in onPostExecute
I finished the Android Nanodegree a while back and remember working on this project. When you instantiate an adapter it will call the getSize() method to determine how many rows to create for the views and then call getView() on each of them to bind the views.
Since your async Task may not have finished downloading the movies, you're passing an empty list to the adapter and thus getting a NullPointerException.
It's always a good approach to instantiate the adapter in the onPostExecute() method of AsyncTask. This method is called on the UI thread after the background thread has finished execution.
So put these two lines of code in onPostExecute() and it should work
MovieAdapter adapter = new MovieAdapter(MainActivity.this, movies);
gridView.setAdapter(adapter);

App Crashes while switching from one Activity to another

Aim: Building app on Google API to fetch the data about the books the user searches
Problem Explanation:
Whenever I hit the submit Button, my app crashes.
This is my first approach in making a network request app and I need guidance.
MainActivityClass
package com.example.vidit.books;
import android.app.Activity;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText query = (EditText) findViewById(R.id.query);
Button submit= (Button) findViewById(R.id.submit);
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent= new Intent(MainActivity.this,Request.class);
intent.putExtra ( "text", query.getText().toString() );
startActivity(intent);
}
});
}
}
Second Class
package com.example.vidit.books;
import android.content.Intent;
public class Request {
Intent i = getIntent();
String text = i.getStringExtra ("text");
public static final String LOG_TAG = Request.class.getSimpleName();
String APIURL="https://www.googleapis.com/books/v1/volumes?q= " + text;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_request);
}
public void UpdateUi(Book book)
{
BookAdapter bookAdapter = new BookAdapter(this,book);
ListView listView= (ListView) findViewById(R.id.listview_all);
}
private class BookAsyncTask extends AsyncTask<URL,Void,Book>
{
#Override
protected Book doInBackground(URL... urls) {
URL url = createUrl(APIURL);
String jsonResponse = "";
try {
jsonResponse = makeHttpRequest(url);
} catch (IOException e) {
// TODO Handle the IOException
}
final Book book = extractFeatureFromJson(jsonResponse);
return book;
}
/**
* Make an HTTP request to the given URL and return a String as the response.
*/
private String makeHttpRequest(URL url) throws IOException {
String jsonResponse = "";
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setReadTimeout(10000 /* milliseconds */);
urlConnection.setConnectTimeout(15000 /* milliseconds */);
urlConnection.connect();
if(urlConnection.getResponseCode()==200) {
inputStream = urlConnection.getInputStream();
jsonResponse = readFromStream(inputStream);
}
} catch (IOException e) {
// TODO: Handle the exception
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (inputStream != null) {
// function must handle java.io.IOException here
inputStream.close();
}
}
return jsonResponse;
}
/**
* Convert the {#link InputStream} into a String which contains the
* whole JSON response from the server.
*/
private String readFromStream(InputStream inputStream) throws IOException {
StringBuilder output = new StringBuilder();
if (inputStream != null) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
BufferedReader reader = new BufferedReader(inputStreamReader);
String line = reader.readLine();
while (line != null) {
output.append(line);
line = reader.readLine();
}
}
return output.toString();
}
/**
* Returns new URL object from the given string URL.
*/
private URL createUrl(String stringUrl) {
URL url = null;
try {
url = new URL(stringUrl);
} catch (MalformedURLException exception) {
Log.e(LOG_TAG, "Error with creating URL", exception);
return null;
}
return url;
}
private Book extractFeatureFromJson(String bookJSON) {
try {
JSONObject baseJsonResponse = new JSONObject(bookJSON);
JSONArray items = baseJsonResponse.getJSONArray("items");
// If there are results in the features array
for(int i=0;i<10;i++)
{
JSONObject firstFeature = items.getJSONObject(i);
JSONArray author=firstFeature.getJSONArray("author");
for(int j=0;j<author.length();j++)
{
JSONObject authorFeature=author.getJSONObject(j);
}
String title = items.getString(Integer.parseInt("title"));
// Create a new {#link Event} object
return new Book(title,author);
}
} catch (JSONException e) {
Log.e(LOG_TAG, "Problem parsing the earthquake JSON results", e);
}
return null;
}
}
}
BookAdapter Class:
package com.example.vidit.books;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.List;
public class BookAdapter extends ArrayAdapter<Book> {
public BookAdapter(Activity context, Book book)
{
super(context,0, (List<Book>) book);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View listItemView = convertView;
if(listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(
R.layout.list_item, parent, false);
}
Book cbook=getItem(position);
TextView title = (TextView) listItemView.findViewById(R.id.title);
title.setText(cbook.getmTitle());
TextView author=(TextView) listItemView.findViewById(R.id.author);
author.setText((CharSequence) cbook.getmAuthor());
return listItemView;
}
}
Showing error in statement:
String text = i.getStringExtra ("text");
Need guidance
I don't know how your code gets compiled when you have overridden onCreate() in Request class and the Request class isn't extending Activity or AppCompatActivity.
Secondly, this line :
Intent i = getIntent();
String text = i.getStringExtra ("text");
should be inside the onCreate() method.
Showing error in statement : String text = i.getStringExtra ("text");
Request for Guidance
Well you need to get the data passed inside onCreate like below.
String APIURL;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_request);
Bundle bundle = getIntent().getExtras();
String text = bundle.getString("text");
APIURL="https://www.googleapis.com/books/v1/volumes?q= " + text;
}
And although you have the asyncTask class i can't see where exactly you execute the class. You need to do that inside onCreate as well.
Try moving this code to your onCreate method
Intent i = getIntent();
String text = i.getStringExtra ("text");
The intent extras is not available in the constructor for your Request class.

Making an app that recieves Json data from tmdb.org

I am trying to make an app where I want my app, on launch, to display a grid of popular movie posters. The movie posters are downloaded from TheMovieDataBase API. I then use Picasso to load the images. For the GridView I am also using a custom adapter. I am not able to understand how to do it. Here is what I have done up till now
MovieFragment.java
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import com.squareup.picasso.Picasso;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MovieFragment extends Fragment {
//ArrayAdapter<String> mMovieAdapter;
String[]movieId,movieTitle,movieOverview,
movieReleaseDate,
moviePosterPath,movieVoteAverage;
public MovieFragment() {
}
MovieAdapter mMovieAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
mMovieAdapter = new MovieAdapter(getActivity());
GridView listView = (GridView) rootView.findViewById(R.id.gridView);
listView.setAdapter(mMovieAdapter);
updateMovie();
return rootView;
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Inflate the menu; this adds items to the action bar if it is present.
inflater.inflate(R.menu.menu_fragment, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_refresh) {
updateMovie();
return true;
}
return super.onOptionsItemSelected(item);
}
private void updateMovie() {
FetchMovieTask movieTask = new FetchMovieTask();
movieTask.execute();
}
class FetchMovieTask extends AsyncTask<Void, Void, List<String>> {
private final String LOG_TAG = FetchMovieTask.class.getSimpleName();
#Override
protected List<String> doInBackground(Void... params) {
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String movieJsonStr = null;
try {
URL url = new URL("http://api.themoviedb.org/3/discover/movie?sort_by=popularity.desc&api_key=c20129fdf73b5df3ab44548ad7f73586");
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
movieJsonStr = buffer.toString();
} catch (IOException e) {
Log.e(LOG_TAG, "Error ", e);
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
try {
return getMovieDataFromJson(movieJsonStr);
} catch (JSONException j) {
Log.e(LOG_TAG, "JSON Error", j);
}
return null;
}
private List<String> getMovieDataFromJson(String forecastJsonStr)
throws JSONException {
JSONObject movieJson = new JSONObject(forecastJsonStr);
JSONArray movieArray = movieJson.getJSONArray("results");
List<String> urls = new ArrayList<>();
for (int i = 0; i < movieArray.length(); i++) {
JSONObject movie = movieArray.getJSONObject(i);
urls.add("http://image.tmdb.org/t/p/w185" + movie.getString("poster_path"));
}
return urls;
}
#Override
protected void onPostExecute(List<String> strings) {
mMovieAdapter.replace(strings);
}
}
class MovieAdapter extends BaseAdapter {
private final String LOG_TAG = MovieAdapter.class.getSimpleName();
private final Context context;
private final List<String> urls = new ArrayList<String>();
public MovieAdapter(Context context) {
this.context = context;
Collections.addAll(urls, moviePosterPath);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = new ImageView(context);
}
ImageView imageView = (ImageView) convertView;
String url = getItem(position);
Log.e(LOG_TAG," URL "+url);
Picasso.with(context).load(url).into(imageView);
return convertView;
}
#Override
public int getCount() {
return urls.size();
}
#Override
public String getItem(int position) {
return urls.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public void replace(List<String> urls) {
this.urls.clear();
this.urls.addAll(urls);
notifyDataSetChanged();
}
}
}
When I run this code it shows a NullPointerException and a RuntimeException
java.lang.RuntimeException: Unable to start activity ComponentInfo
{com.codesetters.verader/com.codesetters.verader.MainActivity}: java.lang.NullPointerException atandroid.app.ActivityThreadperformLaunchActivity(ActivityThread.java:2404)
Caused by: java.lang.NullPointerException atjava.util.Collections.addAll(Collections.java:2582)
How can I resolve them?
Please Help
You're getting this error because you've used moviePosterPath here :
Collections.addAll(urls, moviePosterPath);
but you've not initialized it anywhere. Initialize it with some value and it should solve the error.
The null pointer could be because the String array moviePosterPath is not initialized. and you are ussing it in Collections.addAll
This is how to initialize an array. Anyway I recommend you to use ArrayList
String[] moviePosterPath = new String[N];

When I tap the refresh button the images never appear

I have been trying too hard to get around this problom, when I tap the refresh button in my app, the images doesn't load on the screen.
This the DataFragment file, when i build this app there are no errors.
package com.example.popularmovis;
import android.app.Fragment;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridView;
import android.os.AsyncTask;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.jar.JarException;
/**
* A placeholder fragment containing a simple view.
*/
public class DataFragment extends Fragment {
public ImageAdapter display;
public DataFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add this line in order for this fragment to handle menu events.
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.datafragment_menu, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_refresh) {
FetchMovieData movieData = new FetchMovieData();
movieData.execute();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
display = new ImageAdapter(rootView.getContext());
GridView gridView = (GridView) rootView.findViewById(R.id.gridView_movies);
gridView.setAdapter(display); // uses the view to get the context instead of getActivity().
return rootView;
}
public class FetchMovieData extends AsyncTask<Void, Void, String[]>{
private final String LOG_TAG = FetchMovieData.class.getSimpleName();
private String[] extractdisplayFromJason(String jasnData)
throws JSONException{
//These jason display need to be extracted
final String movie_results = "results";
final String movie_poster = "poster_path";
JSONObject movieData = new JSONObject(jasnData);
JSONArray movieArray = movieData.getJSONArray(movie_results);
String[] posterAddreess = new String[movieArray.length()];
//Fill ther posterAddreess with the URL to display
for(int j=0; j < movieArray.length(); j++){
String posterPath;
JSONObject movieArrayItem = movieArray.getJSONObject(j);
posterPath = movieArrayItem.getString(movie_poster);
posterAddreess[j] = "http://image.tmdb.org/t/p/w185/" + posterPath;
}
for (String s : posterAddreess) {
Log.v(LOG_TAG, "Thumbnail Links: " + s);
}
return posterAddreess;
}
#Override
protected String[] doInBackground(Void... params) {
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
String JsonData = null;
String country = "US";
String rating = "R";
String sort = "popularity.desc";
String apiKey = "";
//building the URL for the movie DB
try {
//building the URL for the movie DB
final String MovieDatabaseUrl = "https://api.themoviedb.org/3/discover/movie?";
final String Country_for_release = "certification_country";
final String Rating = "certification";
final String Sorting_Order = "sort_by";
final String Api_Id = "api_key";
Uri buildUri = Uri.parse(MovieDatabaseUrl).buildUpon()
.appendQueryParameter(Country_for_release, country)
.appendQueryParameter(Rating, rating)
.appendQueryParameter(Sorting_Order, sort)
.appendQueryParameter(Api_Id, apiKey)
.build();
//Converting URI to URL
URL url = new URL(buildUri.toString());
Log.v(LOG_TAG, "Built URI = "+ buildUri.toString());
//Create the request to the Movie Database
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
//Read the input from the database into string
InputStream inputStream = urlConnection.getInputStream();
//StringBuffer for string Manipulation
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
JsonData = buffer.toString();
Log.v(LOG_TAG,"Forecaast Jason String" + JsonData );
} catch (IOException e) {
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}
try {
return extractdisplayFromJason(JsonData);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
}
return null;
}
protected void onPostExecute(String[] posterAddreess) {
for (String poster : posterAddreess) {
display.addItem(poster);
}
}
}
}
This the ImageAdapter code
package com.example.popularmovis;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import com.example.popularmovis.R;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ArrayList<String> images = new ArrayList<String>();
public ImageAdapter(Context c){
mContext = c;
}
#Override
public int getCount(){
return images.size();
}
#Override
public Object getItem(int position){
return images.get(position);
}
public long getItemId(int position){
return 0;
}
public View getView(int position, View convertView, ViewGroup parent){
ImageView imageview;
if (convertView == null){
imageview = new ImageView(mContext);
imageview.setPadding(0, 0, 0, 0);
//imageview.setLayoutParams(new GridLayout.MarginLayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
imageview.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
imageview.setAdjustViewBounds(true);
} else {
imageview = (ImageView) convertView;
}
Picasso.with(mContext).load(images.get(position)).placeholder(R.mipmap.ic_launcher).into(imageview);
return imageview;
}
/*
Custom methods
*/
public void addItem(String url){
images.add(url);
}
public void clearItems() {
images.clear();
}
}
When you use this in your onCreate method like this, it means that the object is local to the method and can't be use in other methods.
ImageAdapter display = new ImageAdapter(rootView.getContext());
First create a global class member variable
private ImageAdapter display;
then inside your onCreate method do this
display = new ImageAdapter(rootView.getContext());

Pass parameter to a URL AsyncTask android

I'm developing an app and now I have to pass a parameter to a RESTful Service's URL. I'm using AsyncTask, and I need to pass a text from a list view as a parameter to the URL, for example: the URL is http://ip:7001/product?product_name=PARAM I need to get the text from the selected item from my list view, and pass as a parameter in PARAM, using AsyncTask. I've already got the text from the item in the listView, now I just need to pass it as a parameter.
This is my AsycTask class:
package com.tumta.henrique.teste;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import com.tumta.henrique.teste.ProdutoFragment;
/**
* Created by Henrique on 18/05/2015.
*/
public class FiltraProduto extends AsyncTask<String, Void, List<String>> {
private ConsultaConcluidaFiltroProdutoListener listener;
public static String URL_STRING = "http://192.168.0.20:7001/com.henrique.rest/api/v1/status/pro_filtro?pro_nome=";
public FiltraProduto(ConsultaConcluidaFiltroProdutoListener listener) {
this.listener = listener;
}
private List<String> InterpretaResultado(String resultado) throws JSONException {
JSONObject object = new JSONObject(resultado);
JSONArray jsonArray = object.getJSONArray("produto");
//JSONObject jsonProduto = jsonArray.getJSONObject(0);
// String id = jsonProduto.getString("pro_id");
//proId = id;
List<Object> listaNomes = new ArrayList<>();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonProdutoInfo = jsonArray.getJSONObject(i);
String proNome= jsonProdutoInfo.getString("pro_nome");
double proPreco = jsonProdutoInfo.getDouble("pro_preco");
double proSdAtual = jsonProdutoInfo.getDouble("pro_sdAtual");
listaNomes.add(i, proNome);
listaNomes.add(i, proPreco);
listaNomes.add(i, proSdAtual);
}
List<String> strings = new ArrayList<String>();
for (Object o : listaNomes) {
strings.add(o != null ? o.toString() : null);
}
return strings;
}
private String ConsultaServidor() throws IOException {
InputStream is = null;
try {
URL url = new URL(URL_STRING);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(10000);
conn.setReadTimeout(15000);
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.connect();
conn.getResponseCode();
is = conn.getInputStream();
Reader reader = null;
reader = new InputStreamReader(is);
char[] buffer = new char[2048];
reader.read(buffer);
return new String(buffer);
} finally {
if (is != null) {
is.close();
}
}
}
#Override
protected List<String> doInBackground(String... params) {
try {
String resultado = ConsultaServidor();
return InterpretaResultado(resultado);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(List<String> result) {
listener.onConsultaConcluida(result);
super.onPostExecute(result);
}
public interface ConsultaConcluidaFiltroProdutoListener {
void onConsultaConcluida(List<String> result);
}
}
In the URL_STRING I need to pass the param at pro_nome=?
Here I get the item text. This is in my Fragment that has the List View:
public String retornaParam(String param){
return param;
}
#Override
public void onConsultaConcluida(List<String> result) {
final ListView listaProdutos = (ListView) getView().findViewById(R.id.listaprodutos);
ArrayAdapter arrayAdapter = new ArrayAdapter<>(getView().getContext(),android.R.layout.simple_list_item_1, result);
listaProdutos.setAdapter(arrayAdapter);
listaProdutos.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parentAdapter, View view, int position,
long id) {
String nomeProduto = listaProdutos.getItemAtPosition(position).toString();
retornaParam(nomeProduto);
Intent intent = new Intent(getActivity(), DetalhesProdutoActivity.class);
//intent.putExtra("pro_nome", listaProdutos.getItemAtPosition(position).toString());
startActivity(intent);
}
});
}
I get the text and store it in param from the retornaParam method.
Does somebody know how to do it?
If you need more information, just let me know.
You pass in params to an AsyncTask using:
YourAsyncTask.execute(yourview.getText(), "and", "more", "params");
You can then access them in
#Override
protected String doInBackground(String... params) {
URL_STRING += params[0];
...
Just add the following code before sending executing your httpClient:
URL_STRING + = textInsideYourTextView;
It should work, just avoid to manipulate your ui elements outside your UI thread.

Categories

Resources