2017-08-16 5 views
-1

私はthemoviedbデータベースからムービーを発見することができるudacity人気ムービーステージ1プロジェクトに取り組んでいます。onCreateメソッドでasynctaskのarraylist結果を取得して表示する方法

Movie,MovieAdapterMainActivity(内部クラスとしてFetchMovieAsyncTask)クラスを作成しました。しかし、私はエラーの下に得続ける

のjava.lang.NullPointerException:nullのオブジェクト参照

これらは、上の 'java.util.List.sizeを(int型)' インターフェイスメソッドを呼び出そうと私コード

Movieクラス:

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クラス:

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

とMainActivityクラス:

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


} 

私はロギングを使用して、正しいJSONの結果を得ることができたが、私は、UIスレッド上でそれを表示することはできません。

どうすればこの問題を解決できますか?

おかげ

*あなたは、アダプタの映画がnullのインスタンス化するとき、私は movies.add(...)後または onPostExecute

答えて

0

にポスター

+0

これは動作します!また、説明に感謝します:D –

0

コールadapter.notifyDataSetChanged()のためのダミー画像を使用していることに注意してください。 asynctaskが並列スレッドで実行されているためです。 asynctaskonPostExecuteメソッドでアダプタをインスタンス化してください。これにより、asynctaskが完了します。

​​
+0

を動作するはずです。また、movies.addパーツはバックグラウンドスレッドにあるので、そこから通知を呼び出すことは意味をなさない。 –

+0

両方を試しましたが、動作しませんでした –

0

私はAndroid Nanodegreeをしばらくやり終え、このプロジェクトの作業を覚えています。アダプタをインスタンス化すると、getSize()メソッドが呼び出され、ビュー用に作成する行の数を決定し、それぞれのビューにバインドするためにgetView()を呼び出します。

あなたの非同期タスクがムービーのダウンロードを完了していない可能性があるので、空のリストをアダプタに渡すので、NullPointerExceptionが表示されます。

onPostExecute() AsyncTaskメソッドでアダプタをインスタンス化するのは、常に良い方法です。このメソッドは、バックグラウンドスレッドの実行が終了した後にUIスレッドで呼び出されます。

だから、次の2行のコードはonPostExecute()に入れて、それは私がのOPにnullポインタ例外を削除すると思ういけない

MovieAdapter adapter = new MovieAdapter(MainActivity.this, movies); 
gridView.setAdapter(adapter); 
関連する問題