문제

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;
    }
도움이 되었습니까?

해결책 2

My problem was static itemDetailsList in MovieListAdapter.

I haven't noticed that and tried everything.

Thanks for replies.

다른 팁

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

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top