ListFragment中的刷新列表

时间:2013-09-20 21:42:46

标签: android listview android-listview android-listfragment

我正在尝试使用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.movi​​es)之后,我遍历整个数组并使用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();
}

1 个答案:

答案 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();
  }