Iqbal Pratama Iqbal Pratama - 2 years ago 146
Android Question

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

Answer Source

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);
    }
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download