为什么recycleview数据无法与服务器端数据库中的数据同步

时间:2016-03-12 17:17:31

标签: android android-fragments android-volley android-recyclerview

我使用restapi为Android中的应用程序提供数据,对于数据库我使用phpmyadmin并在localhost中执行,一切顺利,但是当我在数据库中添加新数据时recycleview无法同步使用数据库中的最新数据,因此当我滑动或滚动我刚刚添加的最新数据时,我recycleview中的数据显示为double,它将永远不会结束。我正在使用模拟器来运行apk。

如果有人可以帮我修改我的代码,我真的很感激。这是我的customVolleyRequest代码:

public class CustomVolleyRequest {

    private static CustomVolleyRequest customVolleyRequest;
    private static Context context;
    private RequestQueue requestQueue;
    private ImageLoader imageLoader;

    private CustomVolleyRequest(Context context) {
        this.context = context;
        this.requestQueue = getRequestQueue();

        imageLoader = new ImageLoader(requestQueue,
                new ImageLoader.ImageCache() {
                    private final LruCache<String, Bitmap>
                            cache = new LruCache<String, Bitmap>(20);

                    @Override
                    public Bitmap getBitmap(String url) {
                        return cache.get(url);
                    }

                    @Override
                    public void putBitmap(String url, Bitmap bitmap) {
                        cache.put(url, bitmap);
                    }
                });
    }

    public static synchronized CustomVolleyRequest getInstance(Context context) {
        if (customVolleyRequest == null) {
            customVolleyRequest = new CustomVolleyRequest(context);
        }
        return customVolleyRequest;
    }

    public RequestQueue getRequestQueue() {
        if (requestQueue == null) {
            Cache cache = new DiskBasedCache(context.getCacheDir(), 10 * 1024 * 1024);
            Network network = new BasicNetwork(new HurlStack());
            requestQueue = new RequestQueue(cache, network);
            requestQueue.start();
        }
        return requestQueue;
    }

    public ImageLoader getImageLoader() {
        return imageLoader;
    }
}

这是我的appconfig类用于存储标记:

public class AppConfig {
    // Server user login url
    public static String URL_LOGIN = "http://192.168.0.13:80/task_manager/v1/login";

    // Server user register url
    public static String URL_REGISTER = "http://192.168.0.13/task_manager/v1/register";

    //URL of my even
    public static final String DATA_URL = "http://192.168.0.13/task_manager/v1/even/";

    //Tags for my JSON

    public static final String TAG_IMAGE_URL = "gambar";
    public static final String TAG_JUDUL = "judul";
    public static final String TAG_DESKRIPSI = "deskripsi";
    public static final String TAG_DUIT = "duit";
    public static final String TAG_PERSEN = "persen";
    public static final String TAG_SISA_HARI = "sisahari";
}

这是getter和setter:

public class Event {
        //Data Variables
        private String imageUrl;
        private String name;
        private String rank;
        private int realName;
        private int createdBy;
        private int firstAppearance;
        //private ArrayList<String> powers;

        //Getters and Setters
        public String getImageUrl() {
            return imageUrl;
        }

        public void setImageUrl(String imageUrl) {
            this.imageUrl = imageUrl;
        }

        //GET AND SET JUDUL
        public String getJudul() {
            return name;
        }

        public void setJudul(String name) {
            this.name = name;
        }

        //GET AND SET DESKRIPSI
        public String getDeskripsi() {
            return rank;
        }

        public void setDeskripsi(String rank) {
            this.rank = rank;
        }

        //GET AND SET DUIT

        public int getDuit() {
            return realName;
        }

        public void setDuit(int realName) {
            this.realName = realName;
        }

        //GET AND SET PERSEN

        public int getPersen() {
            return createdBy;
        }

        public void setPersen(int createdBy) {
            this.createdBy = createdBy;
        }

        //GET AND SET SISA HARI

        public int getSisaHari() {
            return firstAppearance;
        }

        public void setSisaHari(int firstAppearance) {
            this.firstAppearance = firstAppearance;
        }
    }

这是我的主要片段:

package com.anakacara.anakacara.Fragment;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.anakacara.anakacara.App.AppConfig;
import com.anakacara.anakacara.App.Event;
import com.anakacara.anakacara.Helper.CardAdapter;
import com.anakacara.anakacara.R;
import com.anakacara.anakacara.activity.DetailEvent;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import com.android.volley.toolbox.Volley;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

/**
 * A simple {@link Fragment} subclass.
 * Activities that contain this fragment must implement the
 * {@link EventFragment.OnFragmentInteractionListener} interface
 * to handle interaction events.
 * Use the {@link EventFragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class EventFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

    //Creating a List of event
    private List<Event> listEvent;

    //Creating Views
    private RecyclerView recyclerView;
    private RecyclerView.LayoutManager layoutManager;
    private RecyclerView.Adapter adapter;
    private int requestCount = 1;
    private int list;
    private OnFragmentInteractionListener mListener;
    private RequestQueue requestQueue;
    private ProgressBar progressBar;
    private SwipeRefreshLayout swipeRefreshLayout;
    public EventFragment() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment EventFragment.
     */
    // TODO: Rename and change types and number of parameters
    public static EventFragment newInstance(String param1, String param2) {
        EventFragment fragment = new EventFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    private final RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(final RecyclerView recyclerView, final int newState) {
            // code

        }

        @Override
        public void onScrolled(final RecyclerView recyclerView, final int dx, final int dy) {
            // code
            if (isLastItemDisplaying(recyclerView)) {
                //Calling the method getdata again
                getData();
            }
        }
    };
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View x =  inflater.inflate(R.layout.fragment_event,null);;
        progressBar = (ProgressBar) x.findViewById(R.id.progressBar1);
        recyclerView = (RecyclerView) x.findViewById(R.id.recyclerView);
        recyclerView.setHasFixedSize(true);
        layoutManager = new LinearLayoutManager(getActivity());
        recyclerView.setLayoutManager(layoutManager);

        listEvent = new ArrayList<>();
        requestQueue = Volley.newRequestQueue(getActivity());

        swipeRefreshLayout = (SwipeRefreshLayout) x.findViewById(R.id.swipeRefreshLayout);
        swipeRefreshLayout.setOnRefreshListener(this);

        /**
         * Showing Swipe Refresh animation on activity create
         * As animation won't start on onCreate, post runnable is used
         */
        swipeRefreshLayout.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        swipeRefreshLayout.setRefreshing(true);

                                        getData();

                                    }
                                }
        );

        // listEvent = new ArrayList<>();
        // requestQueue = Volley.newRequestQueue(getActivity());
        //Calling method to get data
        //this method is called twice as if you see
        // getData();

//        swipeRefreshLayout= (SwipeRefreshLayout) x.findViewById(R.id.swipeRefreshLayout);
//        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener()
//        {
//            @Override
//            public void onRefresh()
//            {
//                if (isLastItemDisplaying(recyclerView)) {
////Calling the method getdata again
//                    getData();
//                    progressBar.setVisibility(View.GONE);
//                }
//            }
//        });
        recyclerView.addOnScrollListener(rVOnScrollListener);
        adapter = new CardAdapter(listEvent, getActivity());

        //Adding adapter to recyclerview
        recyclerView.setAdapter(adapter);
        RecyclerView.ItemAnimator itemAnimator = new DefaultItemAnimator();
        itemAnimator.setAddDuration(1000);
        itemAnimator.setRemoveDuration(1000);
        recyclerView.setItemAnimator(itemAnimator);
        recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new ClickListener() {
            @Override
            public void onClick(View view, int position) {
                Intent intent = new Intent(getActivity(), DetailEvent.class);
                intent.putExtra("event_judul", listEvent.get(position).getJudul()); //you can name the keys whatever you like
                intent.putExtra("event_deskripsi", listEvent.get(position).getDeskripsi()); //note that all these values have to be primitive (i.e boolean, int, double, String, etc.)
                intent.putExtra("event_duit", listEvent.get(position).getDuit());
                intent.putExtra("event_persen", listEvent.get(position).getPersen()); //note that all these values have to be primitive (i.e boolean, int, double, String, etc.)
                intent.putExtra("event_sisa_hari", listEvent.get(position).getSisaHari());
                intent.putExtra("event_image", listEvent.get(position).getImageUrl());
                startActivity(intent);
            }

            @Override
            public void onLongClick(View view, int position) {
                Toast.makeText(getActivity(), "Kepencet Lama " + position, Toast.LENGTH_LONG).show();
            }
        }));

        return x;
    }
    private JsonArrayRequest getDataFromServer(int requestCount) {
        //Initializing ProgressBar

        swipeRefreshLayout.setRefreshing(true);
        //Displaying Progressbar
        progressBar.setVisibility(View.VISIBLE);
//        getActivity().getParent().setProgressBarIndeterminateVisibility(true);

        //JsonArrayRequest of volley
        JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(AppConfig.DATA_URL + String.valueOf(requestCount),
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        //Calling method parseData to parse the json response
                        parseData(response);

                        //Hiding the progressbar
                        progressBar.setVisibility(View.GONE);
                        swipeRefreshLayout.setRefreshing(false);
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        progressBar.setVisibility(View.GONE);
                        //If an error occurs that means end of the list has reached
                        Toast.makeText(getActivity(), "No More Items Available"+list, Toast.LENGTH_SHORT).show();
                        swipeRefreshLayout.setRefreshing(false);
                    }
                });

        //Returning the request
        return jsonArrayRequest;
    }

    private void getData() {
        //Adding the method to the queue by calling the method getDataFromServer

        requestQueue.add(getDataFromServer(requestCount));
        //Incrementing the request counter


    }

    //This method will parse json data

    private void parseData(JSONArray array) {
        for (int i = 0; i < array.length(); i++) {
            Event event = new Event();
            JSONObject json = null;
            try {
                json = array.getJSONObject(i);

                event.setJudul(json.getString(AppConfig.TAG_JUDUL));
                event.setDeskripsi(json.getString(AppConfig.TAG_DESKRIPSI));
                event.setDuit(json.getInt(AppConfig.TAG_DUIT));
                event.setPersen(json.getInt(AppConfig.TAG_PERSEN));
                event.setSisaHari(json.getInt(AppConfig.TAG_SISA_HARI));
                event.setImageUrl(json.getString(AppConfig.TAG_IMAGE_URL));
                event.setTotal(json.getInt(AppConfig.TAG_TOTAL));


            } catch (JSONException e) {
                e.printStackTrace();
            }
            listEvent.add(event);
        }
        adapter.notifyDataSetChanged();

        if( requestCount <= listEvent.get(0).getTotal())    {
            requestCount++;
        }


        //Finally initializing our adapter

    }
    // TODO: Rename method, update argument and hook method into UI event
    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    @Override
    public void onRefresh() {
        if (isLastItemDisplaying(recyclerView)) {
            getData();
        }
    }


    class RecyclerTouchListener implements RecyclerView.OnItemTouchListener{
        private GestureDetector mGestureDetector;
        private ClickListener mClickListener;


        public RecyclerTouchListener(final Context context, final RecyclerView recyclerView, final ClickListener clickListener) {
            this.mClickListener = clickListener;
            mGestureDetector = new GestureDetector(context,new GestureDetector.SimpleOnGestureListener(){
                @Override
                public boolean onSingleTapUp(MotionEvent e) {
                    return true;
                }

                @Override
                public void onLongPress(MotionEvent e) {
                    View child = recyclerView.findChildViewUnder(e.getX(),e.getY());
                    if (child!=null && clickListener!=null){
                        clickListener.onLongClick(child, recyclerView.getChildAdapterPosition(child));
                    }
                    super.onLongPress(e);
                }
            });
        }

        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
            View child = rv.findChildViewUnder(e.getX(), e.getY());
            if (child!=null && mClickListener!=null && mGestureDetector.onTouchEvent(e)){
                mClickListener.onClick(child, rv.getChildAdapterPosition(child));
            }
            return false;
        }

        @Override
        public void onTouchEvent(RecyclerView rv, MotionEvent e) {

        }

        @Override
        public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

        }
    }

    private boolean isLastItemDisplaying(RecyclerView recyclerView) {
        if (recyclerView.getAdapter().getItemCount() != 0) {
            int lastVisibleItemPosition = ((LinearLayoutManager) recyclerView.getLayoutManager()).findLastCompletelyVisibleItemPosition();
            if (lastVisibleItemPosition != RecyclerView.NO_POSITION && lastVisibleItemPosition == recyclerView.getAdapter().getItemCount() - 1)
                return true;
        }
        return false;
    }
    private RecyclerView.OnScrollListener rVOnScrollListener = new RecyclerView.OnScrollListener(){
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView,
                                         int newState) {
            super.onScrollStateChanged(recyclerView, newState);
//            Toast.makeText(getApplicationContext(),
//                    Config.DATA_URL+String.valueOf(requestCount), Toast.LENGTH_LONG).show();
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            if (isLastItemDisplaying(recyclerView)) {
//Calling the method getdata again
                getData();
                progressBar.setVisibility(View.GONE);
            }

        }
    };
    public static interface ClickListener{
        public void onClick(View view, int position);
        public void onLongClick(View view, int position);
    }
    /**
     * This interface must be implemented by activities that contain this
     * fragment to allow an interaction in this fragment to be communicated
     * to the activity and potentially other fragments contained in that
     * activity.
     * <p>
     * See the Android Training lesson <a href=
     * "http://developer.android.com/training/basics/fragments/communicating.html"
     * >Communicating with Other Fragments</a> for more information.
     */
    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void onFragmentInteraction(Uri uri);
    }
}

这是我的适配器:

package com.anakacara.anakacara.Helper;

/**
 * Created by Philipus on 05/03/2016.
 */

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.anakacara.anakacara.App.CustomVolleyRequest;
import com.anakacara.anakacara.App.Event;
import com.anakacara.anakacara.R;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.NetworkImageView;

import java.util.List;

/**
 * Created by Belal on 11/9/2015.
 */
public class CardAdapter extends RecyclerView.Adapter<CardAdapter.ViewHolder> {

    private ImageLoader imageLoader;
    private Context context;

    //List of eventes
    List<Event> eventes;

    public CardAdapter(List<Event> eventes, Context context){
        super();
        //Getting all the eventA
        this.eventes = eventes;
        this.context = context;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.event_list, parent, false);
        ViewHolder viewHolder = new ViewHolder(v);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {

        Event event =  eventes.get(position);

        imageLoader = CustomVolleyRequest.getInstance(context).getImageLoader();
        imageLoader.get(event.getImageUrl(), ImageLoader.getImageListener(holder.imageView, R.mipmap.ic_launcher, android.R.drawable.ic_dialog_alert));

        holder.imageView.setImageUrl(event.getImageUrl(), imageLoader);
        holder.textViewJudul.setText(event.getJudul());
        holder.textViewRank.setText(event.getDeskripsi());
        holder.textViewRealName.setText(String.valueOf(event.getDuit()));
        holder.textViewCreatedBy.setText(String.valueOf(event.getPersen()));
        holder.textViewFirstAppearance.setText(String.valueOf(event.getSisaHari()));


    }

    @Override
    public int getItemCount() {
        return eventes.size();
    }

    class ViewHolder extends RecyclerView.ViewHolder {
        public NetworkImageView imageView;
        public TextView textViewJudul;
        public TextView textViewRank;
        public TextView textViewRealName;
        public TextView textViewCreatedBy;
        public TextView textViewFirstAppearance;
//        public TextView  textViewPowers;

        public ViewHolder(View itemView) {
            super(itemView);
            imageView = (NetworkImageView) itemView.findViewById(R.id.imageViewHero);
            textViewJudul = (TextView) itemView.findViewById(R.id.textViewJudul);
            textViewRank= (TextView) itemView.findViewById(R.id.textViewRank);
            textViewRealName= (TextView) itemView.findViewById(R.id.textViewRealName);
            textViewCreatedBy= (TextView) itemView.findViewById(R.id.textViewCreatedBy);
            textViewFirstAppearance= (TextView) itemView.findViewById(R.id.textViewFirstAppearance);

        }
    }
}

1 个答案:

答案 0 :(得分:0)

使用Volley队列的onRequestFinishedLitener来更改通知数据集。

class RequestListener implements RequestQueue.RequestFinishedListener {

        @Override
        public void onRequestFinished(Request request) {
   adapter.notifyDatasetChanged();

     }
}

然后

RequestListener rl = new RequestListener();
volley_queue.addRequestFinishedListener(listener);

如果要在列表结束时加载新数据。您将不得不在您的API中创建位于服务器上的页面。你必须逐页访问。根据列表到达结束,您将调用parseJson作为下一页。

您将使用包含下一个数据的新链接调用您的parseJSON方法。为此,您将添加ReyclerView的OnScrollListener。

 class RecyclerViewOnScroll extends RecyclerView.OnScrollListener
    {
        int temp_page_position;
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            if ((list.size()-1 == layoutManager.findLastVisibleItemPosition())) {  
  // Enters to block when last item of RecyclerView has appeared.
}
}
}