【问题标题】:Listview gets "The content of the adapter has changed but ListView did not receive a notification."Listview 得到“适配器的内容已更改,但 ListView 没有收到通知。”
【发布时间】:2014-05-10 20:31:36
【问题描述】:

我尝试在 volley request 中使用 viewpager 和 listview 片段。

当我第一次运行程序时,我可以看到我从 api 接收到的第一页和第二页数据的日志。在这种情况下,第一页显示空白页。

当我滑动到第二页时,如果收到截击请求,我可以看到包含正确数据的页面。同时,我从 api 收到了第 3 页数据(因为 viewpager 创建了第 3 页的实例)。但是当我点击第二页中的项目时,我得到“适配器的内容已更改,但 ListView 没有收到通知。”

如果我没有点击第 2 页中的项目并滑动到第 3 页,我可以看到包含正确数据的第 3 页,当我点击项目时,它会显示正确的活动。

当我从 api 获得响应并尝试 setOffscreenPageLimit(0); 重新加载每个页面但没有任何变化时调用 notifyDataSetChanged();

这是我的 Adapters、Fragment 和 ServiceHandler 类。

电影列表适配器

    public class MovieListAdapter extends BaseAdapter {

    private LayoutInflater l_Inflater;
    private static List<MovieDetailModel> itemDetailsList;
    private RequestQueue queue;
    private ViewHolder holder;

    //Constructor
    public MovieListAdapter(Context context, List<MovieDetailModel> results) {
        itemDetailsList = results;
        l_Inflater = LayoutInflater.from(context);
        queue = VolleySingleton.getInstance().getRequestQueue();
    }

    @Override
    public int getCount() {
        return itemDetailsList.size();
    }

    @Override
    public Object getItem(int i) {
        return itemDetailsList.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int position, View view, ViewGroup viewGroup) {

        //Holder pattern -> If new view required, create item for list
        if (view == null) {
            view = l_Inflater.inflate(R.layout.item_movie, null);

            initializeHolder(view);

            view.setTag(holder);
        } else {
            holder = (ViewHolder) view.getTag();
        }

        setHolderItems(itemDetailsList, position);

        return view;
    }

    static class ViewHolder {
        TextView txt_title;
        TextView txt_synopsis;
        NetworkImageView itemImage;
    }

    private void initializeHolder(View view) {
        holder = new ViewHolder();
        holder.txt_title = (TextView) view.findViewById(R.id.title);
        holder.txt_synopsis = (TextView) view.findViewById(R.id.synopsis);
        holder.itemImage = (NetworkImageView) view.findViewById(R.id.list_image);
    }


    private void setHolderItems(List<MovieDetailModel> movieDetailModels, int position) {
        holder.txt_title.setText(movieDetailModels.get(position).getTitle());

        holder.txt_synopsis.setText(movieDetailModels.get(position).getSynopsis());

        holder.itemImage.setImageUrl(movieDetailModels.get(position).getPosters().getThumbnail(), VolleySingleton.getInstance().getImageLoader());
    }
}

TabsPagerAdapter

公共类 TabsPagerAdapter 扩展 FragmentStatePagerAdapter {

    public TabsPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int index) {

        return MovieListFragment.newInstance(index);

    }

    @Override
    public int getCount() {
        // get item count - equal to number of tabs
        return Constants.TAB_COUNT;
    }

}

电影列表片段

public class MovieListFragment extends Fragment {

    List<MovieDetailModel> movieDetailModelList;
    public static MovieListAdapter movieListAdapter;
    private int viewPagerPage;
    OnMovieSelected movieItemClickListener;

    public static MovieListFragment newInstance(int tabNumver){
        MovieListFragment fragment = new MovieListFragment();
        Bundle args = new Bundle();
        args.putInt(Constants.ARG_TAB_ID,tabNumver);
        fragment.setArguments(args);
        return fragment;
    }

    public  MovieListFragment(){

    }




    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            movieItemClickListener = (OnMovieSelected) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement onMovieSelected");
        }
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        viewPagerPage = getArguments().getInt(Constants.ARG_TAB_ID);

        if (Constants.LOGS_ACTIVE) {
            Log.d("TAB_ID", viewPagerPage + "");
        }



        View rootView = inflater.inflate(R.layout.fragment_movie_list, container, false);

        ListView moviesListView = (ListView) rootView.findViewById(R.id.listview_movie_list);

        setListView(moviesListView);

        return rootView;
    }

    public List<MovieDetailModel> getSelectedMovieList(int tabId) {

        switch (tabId) {
            case 0:
                return ServiceHandler.makeStringVolleyReq(Constants.BOX_OFFICE_LINK, getActivity());
            case 1:
                return ServiceHandler.makeStringVolleyReq(Constants.TOP_RENTALS_LINK, getActivity());
            case 2:
                return ServiceHandler.makeStringVolleyReq(Constants.UPCOMING_LINK, getActivity());
            default:
                return null;
        }

    }

    private void setListView(ListView listView) {




        movieDetailModelList = getSelectedMovieList(viewPagerPage);

        movieListAdapter = new MovieListAdapter(getActivity(), movieDetailModelList);

        listView.setAdapter(movieListAdapter);


        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {

                if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                    movieItemClickListener.onMovieSelected(movieDetailModelList.get(i));
                    Intent intent = new Intent(getActivity(), ActMovieDetails.class);
                    intent.putExtra(Constants.TAG_MOVIE, movieDetailModelList.get(i));
                    startActivity(intent);
                } else {
                    if (Constants.LOGS_ACTIVE) {
                        Log.d("ORIETNTATION", "LANDSCAPE BUTTON");
                    }
                    movieItemClickListener.onMovieSelected(movieDetailModelList.get(i));
                }
            }

        });

    }


    //For Callbacks
    public interface OnMovieSelected {
        public void onMovieSelected(MovieDetailModel movieDetailModel);
    }
}

服务处理程序

 public static List<MovieDetailModel> makeStringVolleyReq(String url, final Context context) {

        RequestQueue queue = VolleySingleton.getInstance().getRequestQueue();

        ImageLoader mImageLoader;

        final List<MovieDetailModel> movieList = new ArrayList<MovieDetailModel>();


        StringRequest stringRequest = new StringRequest(url, new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                // we got the response, now our job is to handle it

                if(Constants.LOGS_ACTIVE) {
                    Log.d("JSON STRING: ", response);
                }



                movieList.addAll(JSONHandler.convertJSONArrayString2MoviesDetailModels(response));

                if(Constants.LOGS_ACTIVE) {
                    for (int i = 0; i < movieList.size(); i++) {
                        Log.d("MOVIE", movieList.get(i).getTitle());
                    }
                }

                //ASK: How to set non-static?
                MovieListFragment.movieListAdapter.notifyDataSetChanged();

                if(SearchResultsActivity.searchResultsMovieListAdapter!=null){
                    SearchResultsActivity.searchResultsMovieListAdapter.notifyDataSetChanged();
                }



            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                //something happened, treat the error.
            }
        });

        queue.add(stringRequest);

        return movieList;
    }

【问题讨论】:

标签: android listview android-fragments android-viewpager android-volley


【解决方案1】:

您正在尝试从不同的线程更新 listView。

您应该在 UI 线程中调用 notifyDataSetChanged() 来解决此问题。

Android basics: running code in the UI thread

【讨论】:

  • 尝试在我的服务处理程序 makeStringVolleyReq 方法中获取一个活动并在那里调用 notifyDataSetChanged(),但一切都一样.. 'activity.runOnUiThread(new Runnable() { @Override public void run() { MovieListFragment .movi​​eListAdapter.notifyDataSetChanged(); } });'
【解决方案2】:

我的问题是 MovieListAdapter 中的静态 itemDetailsList。

我没有注意到这一点并尝试了所有方法。

感谢您的回复。

【讨论】:

    猜你喜欢
    • 2011-09-22
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 2014-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多