2017-08-16 57 views
-1

我正在研究udacity popular movies stage 1項目,該項目將允許我從themoviedb數據庫中發現電影。如何在onCreate方法中獲取並顯示asynctask中的arraylist結果

我創建了Movie,MovieAdapterMainActivity(以FetchMovieAsyncTask作爲內部類)類。不過,我不斷收到以下錯誤

顯示java.lang.NullPointerException:嘗試調用「)詮釋java.util.List.size(」接口方法 對空對象引用

這些都是我的代碼

電影類:

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線程上顯示。

我該如何解決這個問題?由於

*請注意,我用的虛擬形象的海報

回答

0

當你實例化適配器的電影是空的。因爲asynctask正在並行線程中運行。在您的asynctaskonPostExecute方法中實例化您的適配器。這樣你就可以肯定asynctask就完成了。

​​
+0

這個工程!並感謝您的解釋:D –

0

呼叫adapter.notifyDataSetChanged()movies.add(...)後或onPostExecute

+0

我不認爲這將去除有機磷農藥空指針異常。另外movies.add部分在後臺線程中,所以從那裏調用通知沒有任何意義。 –

+0

兩個都試過,沒有工作 –

0

我完成了Android Nanodegree,回來後記得在這個項目上工作。當您實例化適配器時,它將調用getSize()方法來確定爲視圖創建多少行,然後在每個視圖上調用getView()來綁定視圖。

由於您的異步任務可能尚未完成下載電影,因此您會將空列表傳遞給適配器,從而得到NullPointerException

在AsyncTask的onPostExecute()方法中實例化適配器總是一個好方法。在後臺線程完成執行後,在UI線程上調用此方法。

所以就把這兩行代碼在onPostExecute(),它應該工作

MovieAdapter adapter = new MovieAdapter(MainActivity.this, movies); 
gridView.setAdapter(adapter); 
相關問題