我正在尝试使用ListFragment创建一个电影列表(通过以下this tutorial)。在片段中,我有一个Loader和一个AsyncTaskLoader,它从Web服务下载信息。 AsyncTaskLoader正确下载所有信息,并正确执行“onLoadFinished”方法。 在onLoadFinished中,我调用listadapter中的函数来设置新数据,然后调用notifyDataSetChanged()。 我知道适配器中的数据设置正确(日志语句将从适配器类打印第一个电影的标题),但listview将不会显示任何内容。 但是,如果我向适配器的构造函数提供电影列表,它就可以工作。
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中,我只是创建了一个新的适配器(将电影数组传递给构造函数),然后再次调用setListAdapter(),而不是将数据传递给adapter.setData()。它有效,但感觉就像一个丑陋的解决方案(创建和设置新的适配器可能会消耗更多的资源?)。
编辑2 只是为了澄清适配器类中的setData: 将所有数据添加到数组(this.movies)之后,我遍历整个数组并使用Log语句打印每部电影的标题。因此,在调用setData之后,数据存储在适配器类的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();
}
答案 0 :(得分: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();
修改强>
在创建列表视图时,您正在使用此构造函数:
public SimpleMovieListAdapter(Context context, int textViewResourceId){
super(context, textViewResourceId);
this.context = context;
imageLoader = ImageLoader.getInstance();
}
您没有创建数据列表的新实例
尝试添加以下行:this.movies = new ArrayList<MovieInformation>();
并添加其他修复程序,它应该可以正常工作
编辑#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();
}