为什么GridView null在第二次通过onPostExecute()

时间:2016-02-02 22:20:02

标签: android gridview android-asynctask

为了好玩,我要浏览Udacity Popular Movies App教程。我已经设置它,以便工具栏中有一个微调器,它调用MainActivityFragment中的sortMovies(String sortBy)方法。然后sortMovies()调用GetMoviesTask.execute(sortBy)。

当我运行程序时,一切正常。它显示了按人气排序的电影海报的gridView,我在MainActivityFragment的onCreateView()中调用了它。

然而,当我点击微调器并选择按"最高等级"它正确执行GetMoviesTask.execute(我检查了返回的json),但是当它有时间设置GridView适配器时,它表示gridView为null。

这是MainActivity:

public class MainActivity extends AppCompatActivity {

final String SORT_POPULARITY = "popularity.desc";
final String SORT_HIGHEST_RATED = "vote_average.desc";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Spinner spinner = (Spinner) findViewById(R.id.spinner_sort_by);

    ArrayAdapter spinnerAdapter = ArrayAdapter.createFromResource(this,
            R.array.spinner_sort_options,
            R.layout.simple_spinner_layout_item);

    spinner.setAdapter(spinnerAdapter);
    spinnerAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
    spinner.setSelection(0, false);
    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

            MainActivityFragment mainActivityFragment;
            mainActivityFragment = new MainActivityFragment();

            switch (position) {
                case 0:
                    mainActivityFragment.sortMovies(SORT_POPULARITY);
                    break;
                case 1:
                    mainActivityFragment.sortMovies(SORT_HIGHEST_RATED);
                    break;
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

            // sometimes you need nothing here
        }
    });

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@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_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}
}

这是MainActivityFragment:

public class MainActivityFragment extends Fragment {

View rootView;
GridView gridView;
List<Movie> movies = new ArrayList<>();

public MainActivityFragment(){

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    rootView = inflater.inflate(R.layout.fragment_main, container, false);
    gridView = (GridView) rootView.findViewById(R.id.gridView);

    GetMoviesTask getMoviesTask = new GetMoviesTask();
    getMoviesTask.execute("popularity.desc");

    return rootView;
}

@Override
public void onStart() {
    super.onStart();
   // GetMoviesTask getMoviesTask = new GetMoviesTask();
   // getMoviesTask.execute();

}

public void sortMovies(String sortBy) {

    GetMoviesTask getMoviesTask =  new GetMoviesTask();
    getMoviesTask.execute(sortBy);
}

public class GetMoviesTask extends AsyncTask<String, Void, String[]> {


    @Override
    protected String[] doInBackground(String... params) {

        HttpURLConnection urlConnection = null;
        BufferedReader reader = null;
        String sortBy = params[0];
        //Contains the Json Result
        String moviesJson = null;

        try {

            final String API_BASE_URL = "http://api.themoviedb.org/3/discover/movie?";
            final String API_KEY = "b96087f4a03b686eaf542c5df8037005";
            final String API_KEY_PARAM = "api_key";
            final String API_PAGE = "page";
            final String API_SORT_BY = "sort_by";

            Uri apiUri = Uri.parse(API_BASE_URL).buildUpon()
                    .appendQueryParameter(API_SORT_BY, sortBy)
                    .appendQueryParameter(API_PAGE, "1")
                    .appendQueryParameter(API_KEY_PARAM, API_KEY)
                    .build();

            URL url = new URL(apiUri.toString());

            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.connect();
            InputStream inputStream = urlConnection.getInputStream();
            StringBuffer buffer = new StringBuffer();


            if (inputStream == null) {
                moviesJson = null;
            }else {
                reader = new BufferedReader(new InputStreamReader(inputStream));
            }

            String line;
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }

            if (buffer.length() == 0) {
                moviesJson = null;
            }

            ////////////////////////////////////////////////////
            //////////Return the json string containing the movies////////////
            moviesJson = buffer.toString();

        } catch (MalformedURLException e1) {
            e1.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        } catch (NetworkOnMainThreadException e) {
            Log.d("Error: ", e.toString());
        }

        try {
            return getMoviesFromJson(moviesJson);
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(String[] jsonMovieData) {

        if (jsonMovieData != null) {
            try {
                gridView.setAdapter(new ImageAdapter(getContext(), jsonMovieData));
                gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                    public void onItemClick(AdapterView<?> parent, View v,
                                            int position, long id) {

                        //pass the movie to the Detail Activity
                        Intent i = new Intent(getActivity(), MovieDetail.class);
                        i.putExtra("movie", movies.get(position));
                        startActivity(i);

                    }
                });
            } catch (NullPointerException e) {
                e.printStackTrace();
            }

        } else

        {
            Toast.makeText(getContext(), "Nothing to show :(",
                    Toast.LENGTH_LONG).show();
        }

    }

        }


    private String[] getMoviesFromJson(String jsonMovieData) throws JSONException {

        //Json Object(s) to be extracted
        final String TMDB_POSTER = "poster_path";
        final String TMDB_ORIGINAL_TITLE = "original_title";
        final String TMDB_OVERVIEW = "overview";
        final String TMDB_VOTE_COUNT = "vote_count";
        final String TMDB_VOTE_AVERAGE = "vote_average";
        final String TMDB_BACKDROP = "backdrop_path";
        final String TMDB_BASE_POSTER_PATH = "http://image.tmdb.org/t/p/w500/";
        final String TMDB_RESULTS = "results";
        final String TMDB_ID = "id";

        JSONObject moviesJson = new JSONObject(jsonMovieData);
        JSONArray moviesArray = moviesJson.getJSONArray(TMDB_RESULTS);

        String[] posterPaths = new String[moviesArray.length()];


        // Extract movie data and build movie objects
        for(int i = 0; i < moviesArray.length(); i++) {
            Movie movie = new Movie();
            JSONObject movieJson = moviesArray.getJSONObject(i);
            movie.posterPath = TMDB_BASE_POSTER_PATH + movieJson.optString(TMDB_POSTER).toString();
            posterPaths[i] = movie.posterPath;
            movie.title = movieJson.optString(TMDB_ORIGINAL_TITLE).toString();
            movie.description = movieJson.optString(TMDB_OVERVIEW).toString();
            movie.title = movieJson.optString(TMDB_ORIGINAL_TITLE).toString();
            movie.backDrop = movieJson.optString(TMDB_BACKDROP).toString();
            movie.voteAverage = movieJson.optString(TMDB_VOTE_AVERAGE).toString();
            movie.numOfVotes = movieJson.optString(TMDB_VOTE_COUNT).toString();
            movies.add(movie);

        }

        return posterPaths;
    }
}

如上所述,当应用程序加载时,网格视图中的图像加载完全正常,但是当我选择其中一个微调器时,在onPostExecute中它会显示:

02-02 16:03:13.323 19412-19412/com.ferr3t.don.gurumovies W/System.err: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.GridView.setAdapter(android.widget.ListAdapter)' on a null object reference
02-02 16:03:13.333 19412-19412/com.ferr3t.don.gurumovies W/System.err:     at com.ferr3t.don.gurumovies.MainActivityFragment$GetMoviesTask.onPostExecute(MainActivityFragment.java:161)

我确信有一个简单的解决方案,我忽略了,但是连续两天后,我终于转向stackOverflow ...任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:0)

而不是创建新的片段MainActivityFragment mainActivityFragment; mainActivityFragment = new MainActivityFragment();

您应该在当前活动中找到现有的片段。当您创建一个新的但片段尚未附加到活动时,则不会调用createView()方法,从而导致空指针异常。

要查找现有片段:

get currently displayed fragment