如何在onCreate方法中获取并显示来自asynctask的arraylist结果

时间:2017-08-16 14:15:43

标签: android android-asynctask

我正在研究udacity热门电影第一阶段项目,这将允许我从itoviedb数据库中发现电影。

我已创建MovieMovieAdapterMainActivityFetchMovieAsyncTask作为内部类)类。但我一直低于错误

  

java.lang.NullPointerException:尝试调用接口方法   ' int 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线程上显示它。

我该如何解决这个问题?感谢

*请注意我使用虚拟图像作为海报

3 个答案:

答案 0 :(得分:1)

实例化适配器时,电影为空。因为 asynctask 在并行线程中运行。使用 asynctask onPostExecute方法实例化您的适配器。这样您就可以确定 asynctask 已完成。

    @Override
    protected void onPostExecute(ArrayList<Movie> movies) {
        if (movies==null){
            return;
        }

        super.onPostExecute(movies);
        MovieAdapter adapter = new MovieAdapter(MainActivity.this, movies);
        gridView.setAdapter(adapter);
    }

答案 1 :(得分:0)

movies.add(...)之后或onPostExecute

之后致电adapter.notifyDataSetChanged()

答案 2 :(得分:0)

我在一段时间后完成了Android Nanodegree并记住了这个项目的工作。实例化适配器时,它将调用getSize()方法来确定为视图创建的行数,然后在每个上调用getView()来绑定视图。

由于您的异步任务可能尚未完成下载电影,因此您将空列表传递给适配器,从而获得NullPointerException

在AsyncTask的onPostExecute()方法中实例化适配器总是一种很好的方法。在后台线程完成执行后,在UI线程上调用此方法。

所以将这两行代码放在onPostExecute()中,它应该可以正常工作

MovieAdapter adapter = new MovieAdapter(MainActivity.this, movies);
gridView.setAdapter(adapter);
相关问题