2013-09-20 3 views
0

Я пытаюсь создать список фильмов с ListFragment (следующим образом this tutorial). В фрагменте у меня есть Loader и AsyncTaskLoader, который загружает информацию из веб-службы. AsyncTaskLoader корректно загружает всю информацию, и метод «onLoadFinished» выполняется правильно. В onLoadFinished Я вызываю функцию в списке для установки новых данных, а затем вызываю notifyDataSetChanged(). Я знаю, что данные в адаптере установлены правильно (оператор журнала будет печатать заголовок первого фильма из класса адаптера), но listview ничего не покажет. Однако, если я поставлю список фильмов для конструктора адаптера, он работает.Обновление списка в ListFragment

Код для ListFragment (не все код, только код, который устанавливает адаптер, погрузчик и т.д.):

public class MovieListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<List<MovieInformation>>{ 

    public static final String TAG = "MovieListFragment"; 
    private SimpleMovieListAdapter listAdapter; 

    public MovieListFragment() { 
    } 

    @Override public void onActivityCreated(Bundle savedInstanceState) { 
    super.onActivityCreated(savedInstanceState); 

    System.out.println("DataListFragment.onActivityCreated"); 

    setEmptyText("No results"); 
    listAdapter = new SimpleMovieListAdapter(getActivity(), R.layout.movie_list_row_layout); 
    setListAdapter(listAdapter); 
    setListShown(false); 
    getLoaderManager().initLoader(0, null, this); 
} 

Загрузчик:

public Loader<List<MovieInformation>> onCreateLoader(int arg0, Bundle arg1) { 
    Log.d(TAG, "onCreateLoader"); 
    return new MovieListDownloader(getActivity()); 
} 

@Override 
public void onLoadFinished(Loader<List<MovieInformation>> arg0, 
     List<MovieInformation> data) { 
    listAdapter.setData(data); 
    Log.d(TAG, "onLoadFinished"); 
    Log.d(TAG, ("length is: " + data.size())); 
    setListShown(true); 
    /* 
    if(data != null && !data.isEmpty()){ 
     setListShown(true); 
    }else{ 
     setListShownNoAnimation(true); 
    } 
    */ 
} 

@Override 
public void onLoaderReset(Loader<List<MovieInformation>> arg0) { 
    Log.d(TAG, "onLoaderReset"); 
    listAdapter.setData(null); 
} 

Адаптер :

public class SimpleMovieListAdapter extends ArrayAdapter<MovieInformation> { 
    private static final String TAG = "SimpleMovieListAdapter"; 
    private Context context; 
    private List<MovieInformation> movies; 
    ImageLoader imageLoader; 

    public SimpleMovieListAdapter(Context context, int textViewResourceId, 
     List<MovieInformation> objects) { 
     super(context, textViewResourceId, objects); 
     this.context = context; 
     this.movies = objects; 
     imageLoader = ImageLoader.getInstance(); 

    } 
    public SimpleMovieListAdapter(Context context, int textViewResourceId){ 
     super(context, textViewResourceId); 
     this.context = context; 
     imageLoader = ImageLoader.getInstance(); 
    } 

    public void setData(List<MovieInformation> movies){ 
     this.movies = movies; 

     //This log statement will display the title of the first movie in the set (so the list of movies is updated correctly) 
     Log.d(TAG, this.movies.get(0).getTitle()); 
     notifyDataSetChanged(); 
    } 

    public View getView(int position, View convertView, ViewGroup parent){ 
    Log.d(TAG, ("GetView position" + position)); 
    View rowView; 
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    if(convertView == null){ 
     rowView = inflater.inflate(R.layout.movie_list_row_layout, parent, false); 
    } else { 
     rowView = convertView; 
    } 

    TextView titleText = (TextView) rowView.findViewById(R.id.movie_list_title); 
    TextView yearText = (TextView) rowView.findViewById(R.id.movie_list_year); 
    TextView voteAverageText = (TextView) rowView.findViewById(R.id.movie_list_vote_average); 
    ImageView posterView = (ImageView) rowView.findViewById(R.id.movie_list_poster); 
    titleText.setText(movies.get(position).getTitle()); 
    yearText.setText("(" + movies.get(position).getYear() + ")"); 
    voteAverageText.setText(movies.get(position).getFormattedRatingAndVoteCount() + " " + 
      context.getString(R.string.movie_info_votes) + ")"); 


    imageLoader.displayImage((MyApplication.POSTER_SOURCE_ADDRESS + 
      movies.get(position).getPosterPath()), posterView, MyApplication.options); 

    return rowView; 
} 
} 

Редактировать 1 Я нашел решение сразу после размещения вопроса, но я не думаю, что это «хорошее» решение. В onLoadFinished, вместо передачи данных на adapter.setData() Я просто создал новый адаптер (передающий массив фильмов в конструктор), а затем снова вызвал setListAdapter(). Это работает, но похоже на уродливое решение (создание и установка новых адаптеров, вероятно, потребует больше ресурсов?).

Edit 2 Просто чтобы прояснить кое-что о УстановитьДанные в adapterclass: После добавления всех данных в массив (this.movies) цикл I через весь массив и напечатать название для каждого фильма с лог файле заявление. Таким образом, данные сохраняются в arraylist в классе адаптера после вызова setData, но список пока не заполнен данными.

public void setData(List<MovieInformation> movies){ 
     this.movies = movies; 

    if(movies != null){ 
     this.movies.addAll(movies); 

    } 
    for(MovieInformation m : this.movies){ 
     Log.d(TAG, ("movie : " + this.movies.indexOf(m) + " " + this.movies.get(this.movies.indexOf(m)).getTitle())); 
    } 
    notifyDataSetChanged(); 
} 

ответ

0

попробовать это:

а не делать

public void setData(List<MovieInformation> movies){ 
     this.movies = movies; 

     //This log statement will display the title of the first movie in the set (so the list of movies is updated correctly) 
     Log.d(TAG, this.movies.get(0).getTitle()); 
     notifyDataSetChanged(); 
    } 

изменение этой линии this.movies = movies;

в

this.movies.clear(); 
if(movies!=null){ 

this.movies.addAll(movies); } 

notifyDataSetChanged(); 

EDIT

При создании ListView вы используете этот конструктор:

public SimpleMovieListAdapter(Context context, int textViewResourceId){ 
    super(context, textViewResourceId); 
    this.context = context; 
    imageLoader = ImageLoader.getInstance(); 

}

вы не создаете новый экземпляр вашего списка данных попробуйте добавить строку: this.movies = new ArrayList<MovieInformation>();

и добавьте другое исправление, оно должно работать

EDIT # 2 изменения адаптер расширить базовый адаптер, изменить конструктор, как это:

и обновить строку, в которой вы создаете новый адаптер соответственно

public class SimpleMovieListAdapter extends BaseAdapter { 
    private static final String TAG = "SimpleMovieListAdapter"; 
    private Context context; 
    private List<MovieInformation> movies; 
    ImageLoader imageLoader; 

    public SimpleMovieListAdapter(Context context, List<MovieInformation> objects) { 
     this.context = context; 
     this.movies = objects; 
     imageLoader = ImageLoader.getInstance(); 

    } 
    public SimpleMovieListAdapter(Context context){ 
     this.context = context; 
     this.movies = new ArrayList<MovieInformation>(); 
     imageLoader = ImageLoader.getInstance(); 
    } 
+0

К сожалению, этот список будет еще не обновляет. Фильмы будут добавлены в ArrayList в классе Adapter, но getView никогда не будет выполнен (поэтому строки никогда не создаются) – Skrot

+0

Что происходит с нулевой проверкой фильмов в одной строке после разыменования ее без нулевой проверки? –

+0

есть место, где он устанавливает setData (null), он может получить NPE, если вы делаете this.movies.addAll (null) –

Смежные вопросы