我正在尝试使用 ListFragment 创建电影列表(按照本教程)。在片段中,我有一个加载器和一个从 Web 服务下载信息的 AsyncTaskLoader。AsyncTaskLoader 正确下载了所有信息,并且正确执行了“onLoadFinished”方法。在 onLoadFinished 中,我调用 listadapter 中的一个函数来设置新数据,然后调用 notifyDataSetChanged()。我知道适配器中的数据设置正确(日志语句将打印适配器类中第一部电影的标题),但列表视图不会显示任何内容。但是,如果我向适配器的构造函数提供电影列表,它就可以工作。
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()。它可以工作,但感觉像是一个丑陋的解决方案(创建和设置新适配器可能会消耗更多资源?)。
编辑 2 只是为了澄清适配器类中关于 setData 的一些事情:将所有数据添加到数组(this.movies)后,我循环遍历整个数组并使用日志语句打印每部电影的标题。所以数据在调用setData后存储在adapterclass中的arraylist中,但是listview仍然没有填充数据。
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();
}