Question

I tried to use viewpager and listview fragment in it with volley request.

When I first run program, I can see logs that I recieved data from api for both 1st and 2nd page. In that case 1st page shows blank page.

When I swipe to 2nd page I can see page with correct data if volley request came. In the same time I recieved 3rd page data from api(Because viewpager crates an instance of 3rd page). But when I click on item in 2nd page I get "The content of the adapter has changed but ListView did not receive a notification."

If I don't click on item in 2nd page and swipe to 3rd, I can see 3rd page with correct data and when I click on item it shows correct activity.

Invoking notifyDataSetChanged(); when I get response from api and tried setOffscreenPageLimit(0); to reload every page but nothing changes.

Here is my Adapters, Fragment and ServiceHandler classes.

MovieListAdapter

    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

public class TabsPagerAdapter extends 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;
    }

}

MovieListFragment

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);
    }
}

ServiceHandler

 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;
    }
Was it helpful?

Solution 2

My problem was static itemDetailsList in MovieListAdapter.

I haven't noticed that and tried everything.

Thanks for replies.

OTHER TIPS

You are trying to update listView from different thread.

You should call notifyDataSetChanged() in the UI thread to resolve this.

Android basics: running code in the UI thread

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top