2016-12-27 49 views
3

我目前正在創建一個應用程序,它將向最終用戶顯示當前電影海報的網格。我通過使用TheMovieDB API獲取電影數據,並通過使用ASync任務在應用程序中獲取數據。我希望最終能夠在我的應用中實現分頁功能,在這種情況下,用戶會看到電影海報的準無盡網格。何時爲RecyclerView創建新適配器 - notifyDataSet()不工作?

因此,我接觸到這個的方式是我創建了我的Movie模型對象,它將存儲關於每部電影的幾段數據。然後,當我從API中提取數據時,我填充了一個充滿電影對象的ArrayList。但是,我不確定一旦執行分頁後將創建多少部電影。爲了安全起見,我已將我的ArrayList初始化爲不包含任何電影。一旦我的ASync任務完成(如在onPostExecute()中),我會將所有電影添加到我的陣列。

我現在面臨的問題是,在我的任務onPostExecute()內,我認爲notifyDataSetChanged()會給我一個電影海報網格。但是,似乎並非如此。我不確定爲什麼,但我必須用我新添加的數組重新創建適配器,以便海報顯示在屏幕上。我在onPostExecute()中重新創建適配器的唯一原因是因爲我在網絡上的其他地方看到了它,但沒有完全理解它被使用的原因。

這裏是我一起工作的代碼:

package com.example.android.popularmovies_stage1; 

import android.os.AsyncTask; 
import android.os.Bundle; 
import android.support.v7.app.AppCompatActivity; 
import android.support.v7.widget.GridLayoutManager; 
import android.support.v7.widget.RecyclerView; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ImageView; 

import com.squareup.picasso.Picasso; 

import java.util.ArrayList; 
import java.util.List; 

public class MovieSelection extends AppCompatActivity { 

    RecyclerView mRecyclerView; 
    MovieAdapter mAdapter; 
    List<Movie> mMoviesList = new ArrayList<>(); 

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

     mRecyclerView = (RecyclerView) findViewById(R.id.rv_movie_selection); 
     GridLayoutManager layoutManager = new GridLayoutManager(getApplicationContext(), 3); 
     mRecyclerView.setLayoutManager(layoutManager); 

     mRecyclerView.setHasFixedSize(true); 

     mAdapter = new MovieAdapter(mMoviesList); 
     mRecyclerView.setAdapter(mAdapter); 

     new FetchMoviesTask().execute(); 
    } 

    private class MovieAdapter extends RecyclerView.Adapter<MovieHolder>{ 
     private List<Movie> adapterMovies; 

     public MovieAdapter(List<Movie> movies){ 
      adapterMovies = movies; 
     } 

     @Override 
     public MovieHolder onCreateViewHolder(ViewGroup viewGroup, int viewType){ 
      LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext()); 
      View view = inflater.inflate(R.layout.movie_list_item, viewGroup, false); 

      return new MovieHolder(view); 
     } 

     @Override 
     public void onBindViewHolder(MovieHolder holder, int position){ 
      Movie currentMovie = adapterMovies.get(position); 
      Picasso.with(getApplicationContext()) 
        .load("https://image.tmdb.org/t/p/w185/" + currentMovie.getPosterPath()) 
        .into(holder.holderImageView); 
     } 

     @Override 
     public int getItemCount(){ 
      return adapterMovies.size(); 
     } 

    } 

    private class MovieHolder extends RecyclerView.ViewHolder{ 
     ImageView holderImageView; 

     public MovieHolder(View movieView){ 
      super(movieView); 
      holderImageView = (ImageView) movieView.findViewById(R.id.list_item_image_view); 
     } 


    } 


    private class FetchMoviesTask extends AsyncTask<Void, Void, List<Movie>>{ 
     @Override 
     protected List<Movie> doInBackground(Void... params){ 
      return new MovieFetcher().fetchMovies(); 
     } 

     @Override 
     protected void onPostExecute(List<Movie> parsedMovies){ 
      mMoviesList = parsedMovies; 
//   mAdapter.notifyDataSetChanged(); Unsure of why this is not working as I expected? 
      mAdapter = new MovieAdapter(mMoviesList); 
      mRecyclerView.setAdapter(mAdapter); 
     } 
    } 
} 

爲什麼如預期那樣的notifyDataSetChanged()方法不行?如果ArrayList在沒有任何數據的情況下初始化,爲什麼我必須重新創建適配器?當然,對這個問題的任何幫助將不勝感激!

+1

麪糊適配器創建一個方法'addData',只是調用該方法PN'onPostExecute()''一樣mAdpater.setData( ');然後'mAdapter.notifyDataSetChanged();' –

+0

'notifyItemRangeInserted(int positionStart, int itemCount)'也可以使用 – Raghunandan

回答

2

您正在更改哪個Adapter適用的ListView引用。

// New reference which is causing issue, use .addAll() property of ArrayList. 
mMoviesList = parsedMovies;  

更新你的代碼postExecute() -

@Override 
    protected void onPostExecute(List<Movie> parsedMovies){ 
     mMoviesList.addAll(parsedMovies); 
     // Now I am sure this will work :) 
     mAdapter.notifyDataSetChanged(); 
    } 

原因 - 裏面,你的新MovieFetcher().fetchMovies()必須在創建新ArrayList得到postExecute回報,如果分配新的ArrayList到列表將其傳遞給ListView的Adapter,然後引用被更改,並且Adapter不會偵聽更新(notifyDataSetChanged),因爲您的數據集沒有更改,只有引用發生更改。

+0

謝謝!這已經完全解決了我的問題。你的解釋是有道理的:D – coolDude

1
@Override 
    protected void onPostExecute(List<Movie> parsedMovies){ 
     mMoviesList.add(parsedMovies); 
     mAdapter.notifyDataSetChanged(); 
    } 
1

將適配器設置爲RecyclerView之前,您應該調用notifyDataSetChanged()方法。

喜歡:

private class FetchMoviesTask extends AsyncTask<Void, Void, List<Movie>>{ 
    @Override 
    protected List<Movie> doInBackground(Void... params){ 
     return new MovieFetcher().fetchMovies(); 
    } 

    @Override 
    protected void onPostExecute(List<Movie> parsedMovies){ 
     mMoviesList = parsedMovies; 
     mAdapter = new MovieAdapter(mMoviesList); 
     mRecyclerView.setAdapter(mAdapter); 
     mAdapter.notifyDataSetChanged(); 
    } 
} 
1

在onPostExecute()要添加下面一行

mMoviesList = parsedMovies; 

這意味着mMoviesList創建新實例,因此mAdapter.notifyDataSetChanged();將無法​​正常工作。

下面的代碼

private class FetchMoviesTask extends AsyncTask<Void, Void, List<Movie>>{ 
    @Override 
    protected List<Movie> doInBackground(Void... params){ 
     return new MovieFetcher().fetchMovies(); 
    } 

    @Override 
    protected void onPostExecute(List<Movie> parsedMovies){ 
     // mMoviesList.clear();// If you want clear existing data add this line, otherwise remove it 
     if(parsedMovies != null){ 
      mMoviesList.addAll(parsedMovies); 
     } 
     mAdapter.notifyDataSetChanged(); Unsure of why this is not working as I expected? 
    } //end of onPostExecute 
} //end of FetchMoviesTask 

使用您參考check here

相關問題