I have a recyclerview in my project and data not bind to the recyclerview. I am getting data from the server and data correctly come. I put a Toast in the Adapter Class and it is working. I cannot figure out the problem.
Activity Class....
public class ViewDealerCompln extends AppCompatActivity {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_dealer_complain);
typeface = Typeface.createFromAsset(getAssets(), "productsans.ttf");
recyclerView = (RecyclerView) findViewById(R.id.com_recyclerView);
compList = new ArrayList<>();
toolbar = (Toolbar) findViewById(R.id.com_view_app_bar);
TextView mTitle = (TextView) toolbar.findViewById(R.id.toolbar_title);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle("");
mTitle.setText("Complain History");
mTitle.setTypeface(typeface);
repID = DealerListAdapter.getRepID();
dealerID = DealerListAdapter.getDealerID();
mLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setAdapter(adcAdapter);
getData();
}
private void getData() {
String tag_string_req = "req_data";
request = new StringRequest(Request.Method.POST, AppConfig.URL_JSON_GETCOMPLAIN, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response);
if (jsonObject.names().get(0).equals("feed")) {
JSONArray jsonFeedArray = jsonObject.getJSONArray("feed");
if (jsonFeedArray.length() > 0) {
for (int i = 0; i < jsonFeedArray.length(); i++) {
JSONObject currentObject = jsonFeedArray.getJSONObject(i);
String namemm = currentObject.getString("compId");
compList.add(namemm);
}
adcAdapter = new ViewDealerComplainAdapter(ViewDealerCompln.this, compList);
} else {
Toast.makeText(getApplicationContext(), "No data Available!", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(getApplicationContext(), "Invalid Response from the server!", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
};
}
}
Adapter class...
public class ViewDealerComplainAdapter extends RecyclerView.Adapter<ViewDealerComplainAdapter.ItemViewHolder> {
private LayoutInflater inflater;
private ArrayList<String> subList;
private Context context;
public ViewDealerComplainAdapter(Context context, ArrayList<String> a) {
this.context = context;
inflater = LayoutInflater.from(context);
this.subList = a;
Toast.makeText(context, subList.toString(), Toast.LENGTH_SHORT).show();
}
#Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.custom_complain_list_row, parent, false);
ViewDealerComplainAdapter.ItemViewHolder holder = new ViewDealerComplainAdapter.ItemViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
holder.title.setText(subList.get(position));
}
#Override
public int getItemCount() {
return subList.size();
}
public class ItemViewHolder extends RecyclerView.ViewHolder {
private TextView title;
public ItemViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.compHID);
}
}
}
custom row layout...
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="48dp">
<TextView
android:id="#+id/compHID"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:padding="10dp" />
</LinearLayout>
main layout...
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="#+id/com_view_app_bar"
layout="#layout/app_toolbar_send_complain"></include>
<android.support.v7.widget.RecyclerView
android:id="#+id/com_recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
In your activity, before this line recyclerView.setAdapter(adcAdapter);
write
adcAdapter=new ViewDealerComplainAdapter(this,new ArrayList<String>())
In the adapter create a function as follow
public void setData(ArrayList<String> data){
this.sublist=data;
}
Now, in the function getData()
after this
for (int i = 0; i < jsonFeedArray.length(); i++) {
JSONObject currentObject = jsonFeedArray.getJSONObject(i);
String namemm = currentObject.getString("compId");
compList.add(namemm);
}
write
adcAdapter.setData(compList);
adcAdapter.notifyDataSetChanged();
This will make give you the result right as rain
I think it is happening because you have set the adapter before creating object.
recyclerView.setAdapter(adcAdapter);
getData();
You have first set the adapter to recyclerView and then you call getData() method in which you create object of adcAdapter.
after the loading data from the server update RecyclerView
adcAdapter = new ViewDealerComplainAdapter(ViewDealerCompln.this, compList);
adcAdapter.notifyDataSetChanged();
another way
create a method in Adapter
public void setDataChange(List<Object> asList) {
this.List = asList;
//now, tell the adapter about the update
notifyDataSetChanged();
}
and
adcAdapter.setDataChange(list);
your adapter has two parameters context & arrayList, so while creating instance of adapter make sure you are passing both the values to adapter and set the same adapter to your RecyclerView.
mAdapter=new MAdapter(this,list);
mRecyclerView.setAdapter(mAdapter);
once you have data in your list then pass that list to adapter.
You are setting adcAdapter in to recyclerView before initialize it.
Change code as blow.
adcAdapter = new ViewDealerComplainAdapter(ViewDealerCompln.this, compList);
recyclerView.setAdapter(adcAdapter);
Also you need to call notifyDataSetChanged() on adapter to update recycleview when you get response.
adcAdapter.notifyDataSetChanged();
Related
when I send new data or update the info, how can to change my recycle view?
I have used a dapter.notifyDataSetChanged(); , but it's not working...
I tried more method, but it all cannot change my recycler view
in my code
recyclerView = view.findViewById(R.id.recyclerCoin);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
listCoinDiamondModel = new ArrayList<>();
requestQueue = Volley.newRequestQueue(getActivity());
getData();
adapter = new CoinAdapter(listCoinDiamondModel, getActivity());
recyclerView.setAdapter(adapter);
private void sendGift(String postUserID) {
final String postUserIDD = postUserID;
final String GiftAmount = this.GiftAmount.getText().toString().trim();
final String flag = "1";
StringRequest stringRequest = new StringRequest(Request.Method.POST, URL_GIFTCOIN,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response);
String success = jsonObject.getString("success");
if (success.equals("1")){
adapter.notifyDataSetChanged();
}
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(),e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(),"Error" + error.toString(), Toast.LENGTH_SHORT).show();
}
})
{
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
//Log.d("FID", fid);
params.put("fid", fid);
params.put("GiftAmount", GiftAmount);
params.put("flag", flag);
params.put("postUserID", postUserIDD);
params.put("uid", getID);
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
requestQueue.add(stringRequest);
}
private JsonArrayRequest getDataFromServer(int requestCount) {
//Initializing ProgressBar
final ProgressDialog progressDialog = new ProgressDialog(getActivity());
progressDialog.setMessage("Load...");
progressDialog.dismiss();
final String GROUP_LIST = "https://example.com/aaa.php?flag=1&fid="+ getActivity().getIntent().getStringExtra("fid") +"&page="+requestCount;
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(GROUP_LIST,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
parseData(response);
progressDialog.dismiss();
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
progressDialog.dismiss();
Toast.makeText(getActivity(), "No More gift Available", Toast.LENGTH_SHORT).show();
}
});
//Returning the request
return jsonArrayRequest;
}
//This method will get data from the web api
private void getData() {
requestQueue.add(getDataFromServer(requestCount));
requestCount++;
}
//This method will parse json data
private void parseData(JSONArray array) {
for (int i = 0; i < array.length(); i++) {
//Creating the newFeedModel object
final CoinDiamondModel coinDiamondModel = new CoinDiamondModel();
JSONObject json = null;
try {
//Getting json
json = array.getJSONObject(i);
String TAG_Coin = "Coin";
String TAG_Diamond = "Diamond";
String TAG_UserName = "UserName";
String TAG_UserPhoto = "UserPhoto";
String TAG_UserID = "UserID";
//Log.d("NAME111", json.getString(json.getString(TAG_UserName)));
coinDiamondModel.setCoin(json.getString(TAG_Coin));
coinDiamondModel.setDiamond(json.getString(TAG_Diamond));
coinDiamondModel.setGiftFromUserName(json.getString(TAG_UserName));
coinDiamondModel.setGiftFromUserPhoto(json.getString(TAG_UserPhoto));
coinDiamondModel.setGiftFromUserID(json.getString(TAG_UserID));
} catch (JSONException e) {
e.printStackTrace();
}
//Adding the newFeedModel object to the list
listCoinDiamondModel.add(coinDiamondModel);
//adapter.addTheCoinData(coinDiamondModel);
}
//Notifying the adapter that data has been added or changed
adapter.notifyDataSetChanged();
}
who knows what's happen and how can solve this?
could you told me how can I do, please?
adapter all code
public class CoinAdapter extends RecyclerView.Adapter<CoinAdapter.ViewHolder> {
private ImageLoader imageLoader;
private List<CoinDiamondModel> newcoinDiamondLists;
private RequestManager glide;
private Context context;
SessionManager sessionManager;
private String getID,memail;
public CoinAdapter(List<CoinDiamondModel> newcoinDiamondLists, Context context) {
this.newcoinDiamondLists = newcoinDiamondLists;
this.glide = Glide.with(context);
this.context = context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.coinlist, parent, false);
ViewHolder viewHolder = new ViewHolder(v);
sessionManager = new SessionManager(getApplicationContext());
sessionManager.checkLogin();
HashMap<String, String> user = sessionManager.getUserDetail();
getID = user.get(sessionManager.USERID);
memail = user.get(sessionManager.EMAIL);
//String gid = getIntent.getStringExtra("xxx");
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
CoinDiamondModel newCoinDiamondModel = newcoinDiamondLists.get(position);
imageLoader = CustomVolleyRequest.getInstance(context).getImageLoader();
holder.userName.setText(newCoinDiamondModel.getGiftFromUserName());
holder.userID.setText(newCoinDiamondModel.getGiftFromUserID());
holder.coinCount.setText(" x "+newCoinDiamondModel.getCoin());
glide.load(newCoinDiamondModel.getGiftFromUserPhoto()).into(holder.userPhoto);
}
#Override
public int getItemCount() {
return newcoinDiamondLists.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
CircleImageView userPhoto;
TextView userName,userID,coinCount;
ImageView coinImg;
public ViewHolder(#NonNull View itemView) {
super(itemView);
userPhoto = (CircleImageView) itemView.findViewById(R.id.userPhoto);
userName = (TextView) itemView.findViewById(R.id.userName);
coinCount = (TextView) itemView.findViewById(R.id.coinCount);
userID = (TextView) itemView.findViewById(R.id.userID);
coinImg = (ImageView) itemView.findViewById(R.id.coinImg);
}
}
public void addTheCoinData(CoinDiamondModel coinDiamondModel){
if(coinDiamondModel!=null){
newcoinDiamondLists.add(coinDiamondModel);
notifyDataSetChanged();
}else {
throw new IllegalArgumentException("無資料!");
}
}
}
you can again set the adapter to recycler view after the response of the server
public void onResponse(JSONArray response) {
parseData(response);
progressDialog.dismiss();
adapter = new CoinAdapter(listCoinDiamondModel, getActivity());
recyclerView.setAdapter(adapter);
}
solution 2:
in your adapter write a function to update you list
and call function in activity
add this function to the adapter
public void updateList(List<CoinDiamondModel> list){
newcoinDiamondLists = list;
notifyDataSetChanged();
}
and call a function updateList of when you need an update recyclerview
The RecyclerView initialization and notifyDataSetChanged() is used properly. As your question is not clear enough about the Adapter implementation of the RecyclerView, I can give you several suggestions to check.
In RecyclerView.Adapter check if getItemCount() method is properly overriden with returning the list length (not 0) like below:
#Override
public int getItemCount() {
return listdata.length;
}
In RecyclerView.Adapter check if onCreateViewHolder method is properly overriden with proper xml layout like below:
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View listItem= layoutInflater.inflate(R.layout.coin_xml_layout, parent, false);
ViewHolder viewHolder = new ViewHolder(listItem);
return viewHolder;
}
In RecyclerView.Adapter check if RecyclerView.ViewHolder class is properly extended
and linked the UI elements from the xml with the adapter like below:
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView coinTextView;
public ViewHolder(View itemView) {
super(itemView);
this.coinTextView = (TextView) itemView.findViewById(R.id.coinTextView);
}
}
In RecyclerView.Adapter check if onBindViewHolder method is properly overridden and updated the list component UI properly like below:
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
final MyListData myListData = listdata[position];
holder.cointTextView.setText(listdata[position].getCoin());
}
Debug with a breakpoint and check if the listCoinDiamondModel.add(coinDiamondModel) is calling or not and coinDiamondModel object is not empty.
The RecyclerView is placed properly in the activity xml, like the RecyclerView is Visible, has a decent size to show list elements. As an example:
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
you can update your adapter list manually like this:(write this function in your adapter)
public void updateCoinAdapterList(ArrayList<listCoinDiamondModel> recyclerItemsList) {
this.recyclerItemsList = recyclerItemsList;
this.notifyDataSetChanged();
}
you must set your adapter global variable and initialize it in OnCreate or OnResume, and call
adapter.updateCoinAdapterList(listCoinDiamondModel);
when your list changed
i am trying to implement two recyclerview in one layout with same adapter. but only one recyclerview is showing.
MainActivity.java
public class MainActivity extends AppCompatActivity {
List<DataAdapter> ListOfdataAdapter;
String HTTP_JSON_URL = "http://example.com";
String Image_Name_JSON = "Menu_name";
String Image_URL_JSON = "Menu_image";
JsonArrayRequest RequestOfJSonArray ;
RequestQueue requestQueue ;
View view ;
int RecyclerViewItemPosition ;
RecyclerView.LayoutManager layoutManagerOfrecyclerView;
RecyclerView.Adapter recyclerViewadapter;
ArrayList<String> ImageTitleNameArrayListForClick;
long Category_ID;
String MenuAPI;
private RecyclerView secondRecyclerView;
private RecyclerView.LayoutManager secondLayoutManager;
private RecyclerView firstrecyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageTitleNameArrayListForClick = new ArrayList<>();
// menu API url
Intent iGet = getIntent();
Category_ID = iGet.getLongExtra("category_id",0);
MenuAPI += Category_ID;
ListOfdataAdapter = new ArrayList<>();
firstrecyclerView = (RecyclerView) findViewById(R.id.recyclerview1);
firstrecyclerView.setHasFixedSize(true);
layoutManagerOfrecyclerView = new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, true);
firstrecyclerView.setLayoutManager(layoutManagerOfrecyclerView);
firstrecyclerView.post(new Runnable() {
#Override
public void run() {
JSON_HTTP_CALL();// a method which requests remote data
}
});
secondRecyclerView = (RecyclerView) findViewById(R.id.recyclerview2);
secondRecyclerView.setHasFixedSize(true);
secondLayoutManager = new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, true);
secondRecyclerView.setLayoutManager(secondLayoutManager);
secondRecyclerView.post(new Runnable() {
#Override
public void run() {
JSON_HTTP_CALL2();// a method which requests remote data
}
});
// Implementing Click Listener on RecyclerView.
}
public void JSON_HTTP_CALL(){
RequestOfJSonArray = new JsonArrayRequest(HTTP_JSON_URL + "/api/example.php" +"&category_id=2",
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
ParseJSonResponse(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue = Volley.newRequestQueue(MainActivity.this);
requestQueue.add(RequestOfJSonArray);
}
public void ParseJSonResponse(JSONArray array){
for(int i = 0; i<array.length(); i++) {
DataAdapter GetDataAdapter2 = new DataAdapter();
JSONObject json = null;
try {
json = array.getJSONObject(i);
GetDataAdapter2.setImageTitle2(json.getString(Image_Name_JSON));
// Adding image title name in array to display on RecyclerView click event.
ImageTitleNameArrayListForClick.add(json.getString(Image_Name_JSON));
GetDataAdapter2.setImageUrl2(HTTP_JSON_URL + "/" + json.getString(Image_URL_JSON));
} catch (JSONException e) {
e.printStackTrace();
}
ListOfdataAdapter.add(GetDataAdapter2);
}
recyclerViewadapter = new RecyclerViewAdapter(ListOfdataAdapter, getApplicationContext());
firstrecyclerView.setAdapter(recyclerViewadapter);
}
public void JSON_HTTP_CALL2(){
RequestOfJSonArray = new JsonArrayRequest(HTTP_JSON_URL + "/api/example.php" +"&category_id=2",
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
ParseJSonResponse2(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue = Volley.newRequestQueue(MainActivity.this);
requestQueue.add(RequestOfJSonArray);
}
public void ParseJSonResponse2(JSONArray array){
for(int i = 0; i<array.length(); i++) {
DataAdapter GetDataAdapter2 = new DataAdapter();
JSONObject json = null;
try {
json = array.getJSONObject(i);
GetDataAdapter2.setImageTitle2(json.getString(Image_Name_JSON));
// Adding image title name in array to display on RecyclerView click event.
ImageTitleNameArrayListForClick.add(json.getString(Image_Name_JSON));
GetDataAdapter2.setImageUrl2(HTTP_JSON_URL + "/" + json.getString(Image_URL_JSON));
} catch (JSONException e) {
e.printStackTrace();
}
ListOfdataAdapter.add(GetDataAdapter2);
}
recyclerViewadapter = new RecyclerViewAdapter(ListOfdataAdapter, getApplicationContext());
secondRecyclerView.setAdapter(recyclerViewadapter);
}
}
Adapter class
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
Context context;
List<DataAdapter> dataAdapters;
ImageLoader imageLoader;
private Activity activity;
private static final int CITY_TYPE = 0;
JsonArrayRequest RequestOfJSonArray;
private static final int EVENT_TYPE = 1;
public RecyclerViewAdapter(Activity act) {
this.activity = act;
}
public RecyclerViewAdapter(List<DataAdapter> getDataAdapter, Context context){
super();
this.dataAdapters = getDataAdapter;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case CITY_TYPE:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview, parent, false);
return new ViewHolder(view);
case EVENT_TYPE:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.card2, parent, false);
return new ViewHolder(view);
}
return null;
}
#Override
public void onBindViewHolder(ViewHolder Viewholder, int position) {
DataAdapter dataAdapterOBJ = dataAdapters.get(position);
imageLoader = ImageAdapter.getInstance(context).getImageLoader();
if (dataAdapterOBJ != null) {
switch (dataAdapterOBJ.getType()) {
case CITY_TYPE:
imageLoader.get(dataAdapterOBJ.getImageUrl2(),
ImageLoader.getImageListener(
Viewholder.VollyImageView,//Server Image
R.mipmap.ic_launcher,//Before loading server image the default showing image.
android.R.drawable.ic_dialog_alert //Error image if requested image dose not found on server.
)
);
Viewholder.VollyImageView.setImageUrl(dataAdapterOBJ.getImageUrl2(), imageLoader);
Viewholder.ImageTitleTextView.setText(dataAdapterOBJ.getImageTitle2());
break;
case EVENT_TYPE:
imageLoader.get(dataAdapterOBJ.getImageUrl2(),
ImageLoader.getImageListener(
Viewholder.VollyImageView,//Server Image
R.mipmap.ic_launcher,//Before loading server image the default showing image.
android.R.drawable.ic_dialog_alert //Error image if requested image dose not found on server.
)
);
Viewholder.VollyImageView.setImageUrl(dataAdapterOBJ.getImageUrl2(), imageLoader);
Viewholder.ImageTitleTextView.setText(dataAdapterOBJ.getImageTitle2());
break;
}
}
}
#Override
public int getItemCount() {
return dataAdapters.size();
}
class ViewHolder extends RecyclerView.ViewHolder{
public TextView ImageTitleTextView;
public NetworkImageView VollyImageView ;
public ViewHolder(View itemView) {
super(itemView);
ImageTitleTextView = (TextView) itemView.findViewById(R.id.MenuNameTV) ;
VollyImageView = (NetworkImageView) itemView.findViewById(R.id.VolleyImageView) ;
}
}
}
main activity xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="Most Watched"/>
<!-- A RecyclerView to display horizontal list -->
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview1"
android:scrollbars="none"
android:layout_width="fill_parent"
android:layout_height="240dp"
android:paddingLeft="0dp"
android:paddingRight="15dp"
android:paddingTop="15dp"
android:paddingBottom="25dp"
android:background="#ffc000"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="All Dramas"/>
<!-- A RecyclerView to display vertical list -->
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview2"
android:layout_width="fill_parent"
android:layout_height="240dp"
android:paddingLeft="0dp"
android:paddingRight="15dp"
android:paddingTop="15dp"
android:paddingBottom="25dp"/>
i try every possible way available on internet but dont get solution.
Anything wrong i am doing?
any idea how to run two recyclerview with above code.
thankx
You can do this-
<android.support.v4.widget.NestedScrollView>
<LinearLayout>
.
.
.
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
This is used to attach 2 or more scrolling views together and one more thing you can do is to make the height of recycler view as "wrap_content".
Hope this helps.
I'm working on an app that hits a web service every 10 seconds to fetch data and then populate it in a RecyclerView, if there is any data present in the JSONarray returned. Once the data is retrieved by the application, the retrieved data will be removed from the server. So that the next time the app hits the web service it may get empty arrays until the new data comes in the server.
The Problem:
The RecyclerView disappears when the phone is rotated or the screen orientation is changed. This may be because, android usually destroys your application’s existing Activities and recreates them when the orientation is changed. But in my case the already retrieved data will not be present in the server so the it could be showed after the activity is recreated.
I think it has to do something with saving the state by implementing the onSaveInstanceState method, but not sure on how to implement it in my code. Can anyone please tell me what changes are to be made.
MainActivity.java
public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener{
List<DataModel> DataAdapterClassList;
RecyclerView recyclerView;
LinearLayoutManager recyclerViewlayoutManager;
RecyclerView.Adapter recyclerViewadapter;
ArrayList<String> SubjectNames;
RequestQueue requestQueue ;
SwipeRefreshLayout mSwipeRefreshLayout;
public MainActivity mainActivity;
View ChildView ;
int RecyclerViewClickedItemPOS ;
private static final String TAG = MainActivity.class.getSimpleName();
.....//More declarations
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainActivity = this;
mRequestingLocationUpdates = false;
mLastUpdateTime = "";
// Update values using data stored in the Bundle.
updateValuesFromBundle(savedInstanceState);
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mSettingsClient = LocationServices.getSettingsClient(this);
setContentView(R.layout.activity_main);
DataAdapterClassList = new ArrayList<>();
SubjectNames = new ArrayList<>();
recyclerView = (RecyclerView) findViewById(R.id.recyclerView1);
recyclerView.setHasFixedSize(true);
recyclerViewlayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(recyclerViewlayoutManager);
recyclerViewlayoutManager.setReverseLayout(true);
recyclerViewlayoutManager.setStackFromEnd(true);
......//location callbacks....
startTimer();
JSON_WEB_CALL();
}
/**Location Updates fields based on data stored in the bundle.*/
private void updateValuesFromBundle(Bundle savedInstanceState) {
if (savedInstanceState != null) {
if (savedInstanceState.keySet().contains(KEY_REQUESTING_LOCATION_UPDATES)) {
mRequestingLocationUpdates = savedInstanceState.getBoolean(
KEY_REQUESTING_LOCATION_UPDATES);
}
if (savedInstanceState.keySet().contains(KEY_LOCATION)) {
mCurrentLocation = savedInstanceState.getParcelable(KEY_LOCATION);
}
// Update the value of mLastUpdateTime from the Bundle and update the UI.
if (savedInstanceState.keySet().contains(KEY_LAST_UPDATED_TIME_STRING)) {
mLastUpdateTime = savedInstanceState.getString(KEY_LAST_UPDATED_TIME_STRING);
}
updateUI();
}
}
#Override
public void onResume() {
super.onResume();
}
.............//More Location Codes
#Override
public void onRefresh() {
mSwipeRefreshLayout.setRefreshing(false);
JSON_WEB_CALL();
}
public void JSON_WEB_CALL(){
String HTTP_SERVER_URL= String.format("http://pastebin.com/mySampleApi/student/%1$s",mStudentRoll);
JsonArrayRequest jsArrRequest = new JsonArrayRequest
(Request.Method.POST, HTTP_SERVER_URL, null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
//mTxtDisplay.setText("Response: " + response.toString());
JSON_PARSE_DATA_AFTER_WEBCALL(response);
Log.i(TAG, "Hello");
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
}
}){
};
requestQueue = Volley.newRequestQueue(this);
requestQueue.add(jsArrRequest);
}
public void JSON_PARSE_DATA_AFTER_WEBCALL(JSONArray array){
for(int i = 0; i<array.length(); i++) {
DataModel GetDataModel = new DataModel();
JSONObject json = null;
try {
json = array.getJSONObject(i);
GetDataModel.setId(json.getString("CLASS"));
GetDataModel.setPlateNo(json.getString("HOUSE"));
GetDataModel.setPlateCode(json.getString("IMAGEURL"));
} catch (JSONException e) {
e.printStackTrace();
}
DataAdapterClassList.add(GetDataModel);
mSwipeRefreshLayout.setRefreshing(false);
}
if (array.length() != 0) {
recyclerViewadapter = new NewRecyclerViewAdapter(DataAdapterClassList, this);
recyclerView.setAdapter(recyclerViewadapter);
SHOW_ALERT(array);
sendNotification(recyclerView, array);
}
}
#Override
public void onPause() {
super.onPause();
}
#Override
public void onBackPressed() {
moveTaskToBack(true);
}
}
NewRecyclerViewAdapter.java
public class NewRecyclerViewAdapter extends RecyclerView.Adapter<NewRecyclerViewAdapter.ViewHolder> {
Context context;
List<DataModel> dataModels;
private static int currentPosition = 0;
public Animation animationUp;
public Animation animationDown;
public int mExpandedPosition=-1;
public NewRecyclerViewAdapter(List<DataModel> getDataAdapter, Context context){
super();
this.dataModels = getDataAdapter;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.new_card_view, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
DataModel dataAdapter = dataModels.get(position)
viewHolder.SudentClass.setText(dataAdapter.getSudentClass());
viewHolder.SudentHouse.setText(dataAdapter.getSudentHouse());
Glide.with(context).load(dataAdapter.getImgUrl()).into(viewHolder.imageView);
viewHolder.linearLayout.setVisibility(View.GONE);
final boolean isExpanded = position==mExpandedPosition;
viewHolder.linearLayout.setVisibility(isExpanded?View.VISIBLE:View.GONE);
viewHolder.itemView.setActivated(isExpanded);
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mExpandedPosition = isExpanded ? -1:position;
//TransitionManager.beginDelayedTransition();
notifyDataSetChanged();
}
});
}
#Override
public int getItemCount() {
return dataModels.size();
}
dataAdapter.getSudentClass() ViewHolder extends RecyclerView.ViewHolder{
public TextView StudentdataAdapter.getSudentClass();
public TextView SudentHouse;
public TextView StudentClass;
public ImageView imageView;
LinearLayout linearLayout;
public ViewHolder(View itemView) {
super(itemView);
SudentHouse = (TextView) itemView.findViewById(R.id.vehicle_SudentHouse) ;
StudentClass = (TextView) itemView.findViewById(R.id.vehicle_student_class) ;
imageView = (ImageView) itemView.findViewById(R.id.imageView);
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/no_conn_layout"
android:orientation="horizontal"
android:visibility="visible">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No Connection!!!"/>
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Try Again" />
</LinearLayout>
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.newcoder.student.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</android.support.v4.widget.SwipeRefreshLayout>
Please go through the link below -
https://developer.android.com/guide/topics/resources/runtime-changes.html#RetainingAnObject.
Idea is simple, If we set the
// retain this fragment
setRetainInstance(true);
inside fragment, then this fragment will not be destroyed when configuration is changed. Call your API in this fragment and get the data using getters and setters, so that you wont lose the data.
You have to handle the Configuration change in a Effective Manner
Try this code in your project
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
mListState=recyclerView.getLayoutManager().onSaveInstanceState();
mBundleRecyclerViewState.putParcelable(KEY_RECYCLER_STATE, mListState);
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (mBundleRecyclerViewState != null) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mListState = mBundleRecyclerViewState.getParcelable(KEY_RECYCLER_STATE);
recyclerView.getLayoutManager().onRestoreInstanceState(mListState);
}
}, 50);
}
recyclerView.setLayoutManager(gridLayoutManager);
}
Here i have used GridLayoutManager, for your purpose you can use LinearLayout.
Here is the github link for complete working project
Image Gallery Using RecyclerView
when you rotate screen that state will be saved is required used below code for.... in mainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
if(savedInstanceState != null) {
DataAdapterClassList = savedInstanceState.getIntegerArrayList("key");
}
// Pass the imagesState to the adapter as a parameter here
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putIntegerArrayList("key", DataAdapterClassList);
}
I'm trying to display an ArrayList of Integers inside of a RecyclerView, the Integer values in the ArrayList are downloaded from JSON, all that is done, the thing I need help with is to display them in a RecyclerView.
This is my code so far but the RecyclerView does not display anything.
All code updated to my current code
Here's part of the MainActivity:
public class MainActivity extends AppCompatActivity {
private ActivityMainViewModel viewmodel;
RecyclerView recyclerView;
MainAdapter mAdapter;
public static ArrayList<Integer> rideList = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
viewmodel = new ActivityMainViewModel();
binding.setViewmodel(viewmodel);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
mAdapter = new MainAdapter(rideList);
recyclerView.setAdapter(mAdapter);
}
Here's the MainAdapter class:
class MainAdapter extends android.support.v7.widget.RecyclerView.Adapter<MainAdapter.ViewHolder> {
private ArrayList<Integer> rideList;
public MainAdapter(ArrayList<Integer> rideList)
{
this.rideList = rideList;
}
#Override
public MainAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(MainAdapter.ViewHolder holder, int position)
{
holder.rideHeight.setText(String.valueOf(rideList.get(position)));
}
#Override
public int getItemCount()
{
return rideList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView rideHeight;
public ViewHolder(View itemView) {
super(itemView);
rideHeight = (TextView) itemView.findViewById(R.id.rideHeight_textView);
}
}
}
row.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/rideHeight_textView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="20sp"/>
</LinearLayout>
I know that it probably looks a mess but that's because I have been searching both on google and youtube on how to use RecyclerView so I might have mixed from different tutorials and tried somethings myself.
Thanks!
Edit: JsonData code added on request:
JsonData:
public class JsonData
{
public ObservableField<String> dropHeight = new ObservableField<>();
public ObservableField<String> rideCount = new ObservableField<>();
int eID;
int sID;
public JsonData()
{
dropHeight.set("");
rideCount.set("");
}
public void downloadFromSkistar()
{
if (SettingsActivity.submitClicked)
{
eID = SettingsActivity.x;
sID = SettingsActivity.y;
}
else
{
eID = 3206;
sID = 11;
}
try
{
URL url = new URL("https://www.skistar.com/myskistar/api/v2/views/statisticspage.json?entityId=" + eID + "&seasonId=" + sID + " ");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
// Starts the query
conn.connect();
int response = conn.getResponseCode();
Log.i("AndroidExample", "Response: " + response);
if (response == 200)
{
String json = getJson(conn.getInputStream());
JSONObject jsonObject = new JSONObject(json);
JSONArray jsonArray = jsonObject.getJSONArray("rideStatistics");
int reponame = 0;
int rHeight = 0;
for (int i = 0; i < jsonArray.length(); i++)
{
JSONObject skiRun = jsonArray.getJSONObject(i);
reponame += skiRun.getInt("height");
rHeight += skiRun.getInt("height");
MainActivity.rideList.add(new Integer(rHeight));
rHeight = 0;
}
final int height = reponame;
final int count = jsonArray.length();
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
dropHeight.set("" + height);
rideCount.set("" + count);
}
});
}
}
catch (Exception e)
{
Log.i("AndroidExample", "Error");
}
finally
{
}
}
private String getJson(InputStream stream) throws IOException
{
BufferedReader reader;
reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
StringBuilder builder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
builder.append(line + '\n');
}
//Should be placed in finally
stream.close();
return builder.toString();
}
}
You can use like..
Model..to set value and get value
public class CustomModel {
private int it;
public int getIt() {
return it;
}
public void setIt(int it) {
this.it = it;
}
}
Adapter ...
private class MainAdapter extends RecyclerView.Adapter<MainAdapter.ViewHolder>{
public MainAdapter(ArrayList<CustomModel> list){
dataSet = list;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View itemLayoutView = LayoutInflater.from(viewGroup.getContext()).inflate(
R.layout.row, null);
itemLayoutView.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT));
MainAdapter.ViewHolder viewHolder = new MainAdapter.ViewHolder(itemLayoutView);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
CustomModel cardModel = dataSet.get(position);
viewHolder.rideHeight_textView.setText(String.valueOf(cardModel.getId()));
}
#Override
public int getItemCount() {
return dataSet.size();
}
public void updateList(List<CustomModel> temp) {
dataSet = (ArrayList<CustomModel>) temp;
notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView rideHeight_textView;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
rideHeight_textView = (TextView) itemLayoutView .findViewById(R.id.rideHeight_textView);
itemLayoutView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//action ****
}
});
}
}
}
Just call like
ArrayList<CustomModel> menuList = new ArrayList<>();
CustomModel c = new CustomModel();
c.setIt(1);
recyclerView.setHasFixedSize(true);
// ListView
recyclerView.setLayoutManager(new LinearLayoutManager(Your activity.this));
// create an Object for Adapter
MainAdapter mAdapter = new MainAdapter(menuList);
// set the adapter object to the Recyclerview
recyclerView.setAdapter(mAdapter);
row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="#ffffff"
android:padding="#dimen/activity_vertical_margin"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/rideHeight_textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#000000"
android:textSize="20sp"/>
</LinearLayout>
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
LinearLayoutManager layoutManager = new LinearLayoutManager(context);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
mAdapter = new MainAdapter(JsonData.rideList, MainActivity.this);
recyclerView.setAdapter(mAdapter);
mAdapter.notifyDataSetChanged();
adapter:
class MainAdapter extends android.support.v7.widget.RecyclerView.Adapter<MainAdapter.ViewHolder> {
private ArrayList<Integer> rideList = new ArrayList<>();
private Context context;
public MainAdapter(ArrayList<Integer> rideList, Context context)
{
this.context = context;
this.rideList = rideList;
}
#Override
public MainAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(context).inflate(R.layout.row, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(MainAdapter.ViewHolder holder, int position)
{
holder.rideHeight.setText(String.valueOf(rideList.get(position)));
}
#Override
public int getItemCount()
{
return rideList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView rideHeight;
public ViewHolder(View itemView) {
super(itemView);
rideHeight = (TextView) itemView.findViewById(R.id.rideHeight_textView);
}
}
}
row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="#ffffff"
android:padding="#dimen/activity_vertical_margin"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/rideHeight_textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#000000"
android:textSize="20sp"/>
</LinearLayout>
For starters you are not calling your data fetcher method in JsonData class. Your code is kind of messy so you can try the following solution:
In your adapter class add this method:
public void setList(ArrayList<Integer> rideList)
{
this.rideList = rideList;
notifyDataSetChanged();
}
Then in you JsonData class add:
private MainAdapter adapter;
public JsonData(MainAdapter adapter)
{
this.adapter = adapter;
dropHeight.set("");
rideCount.set("");
}
And change downloadFromSkistar to:
public void downloadFromSkistar()
{
if (SettingsActivity.submitClicked)
{
eID = SettingsActivity.x;
sID = SettingsActivity.y;
}
else
{
eID = 3206;
sID = 11;
}
new AsyncTask<Void, Void, List<Integer>>() {
#Override
protected List<Integer> doInBackground(Void... voids) {
try
{
URL url = new
URL("https://www.skistar.com/myskistar/api/v2/views/statisticspage.json?
entityId=" + eID + "&seasonId=" + sID + " ");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
// Starts the query
conn.connect();
int response = conn.getResponseCode();
Log.i("AndroidExample", "Response: " + response);
if (response == 200)
{
String json = getJson(conn.getInputStream());
JSONObject jsonObject = new JSONObject(json);
JSONArray jsonArray = jsonObject.getJSONArray("rideStatistics");
int reponame = 0;
int rHeight = 0;
for (int i = 0; i < jsonArray.length(); i++)
{
JSONObject skiRun = jsonArray.getJSONObject(i);
reponame += skiRun.getInt("height");
rHeight += skiRun.getInt("height");
rideList.add(new Integer(rHeight));
rHeight = 0;
}
}
}
catch (Exception e)
{
Log.i("AndroidExample", "Error");
}
finally
{
}
return rideList;
}
#Override
protected void onPostExecute(List<Integer> list)
{
super.onPostExecute(list);
adapter.setList(rideList);
}
};
}
And in the end finally change MainActivity to:
public class MainActivity extends AppCompatActivity {
private ActivityMainViewModel viewmodel;
RecyclerView recyclerView;
MainAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
viewmodel = new ActivityMainViewModel();
binding.setViewmodel(viewmodel);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
mAdapter = new MainAdapter(JsonData.rideList);
recyclerView.setAdapter(mAdapter);
new JsonData(mAdapter).downloadFromSkistar();
}
PS: You are going to get NetworkOnMainThread exception. So try to add the network code in AsyncTask
Here's what I did to solve it, and btw I'm also using the SwipeRefreshLayout.
public class MainActivity extends AppCompatActivity {
private ActivityMainViewModel viewmodel;
RecyclerView recyclerView;
MainAdapter mAdapter;
public static ArrayList<Integer> rideList = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
viewmodel = new ActivityMainViewModel();
binding.setViewmodel(viewmodel);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
mAdapter = new MainAdapter(rideList);
recyclerView.setAdapter(mAdapter);
viewmodel.jdDownloadFromSkistar();
final SwipeRefreshLayout swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipelayout);;
swipeRefreshLayout.setColorSchemeResources(R.color.refresh,R.color.refresh1,R.color.refresh2);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
swipeRefreshLayout.setRefreshing(true);
refreshRecyclerView();
swipeRefreshLayout.setRefreshing(false);
}
});
}
private void refreshRecyclerView()
{
mAdapter.notifyDataSetChanged();
}
So what I did was make a call to the jdDownloadFromSkistar(); Method and when I swipe to refresh it updates the adapter by using the notifyDataSetChanged(); method.
I know that this question was asked many times before, but i'm confused why sometimes the data is loaded and sometimes data isn't loaded once i get to the end of list. Also when i go fast scrolling through the list, and the new data has been loaded, but immediately it returns me to the first item in list and remove all new loaded items from the next page from server. So that is the second problem and the third problem is that when i load items using SwipeRefreshLayout, i'm also not getting new items when i reach the end of the list.
I have implemented this in my project: https://gist.github.com/ssinss/e06f12ef66c51252563e
list.setLayoutManager(manager);
list.setEmptyView(emptyView);
list.setItemAnimator(new DefaultItemAnimator());
list.setAdapter(mAdapter);
loadJokes(1);
list.addOnScrollListener(new EndlessRecyclerOnScrollListener(manager) {
#Override
public void onLoadMore(final int current_page) {
loadMoreJokes(current_page);
}
});
Here is the method where i'm loading more items from server:
private void loadMoreJokes(int current_page) {
StringRequest request = new StringRequest(Request.Method.GET, AppConfig.URL_GET_ALL_JOKES + current_page,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
hideDialog();
try {
JSONObject object = new JSONObject(response);
boolean error = object.getBoolean("error");
JSONArray jokes = object.getJSONArray("jokes");
if (!error) {
for (int i = 0; i < jokes.length(); i++) {
JSONObject object1 = jokes.getJSONObject(i);
Joke joke = new Joke();
joke.setId(object1.optInt("id"));
joke.setLikes(object1.optInt("likes"));
joke.setComments(object1.optInt("comments"));
joke.setJoke(object1.optString("joke"));
joke.setCreatedAt(object1.optString("created_at"));
joke.setName(object1.optString("user_name"));
joke.setImagePath(object1.optString("image_path"));
joke.setFacebookUserId(object1.optString("facebook_user_id"));
joke.setCategory(object1.optString("category"));
mJokes.add(joke);
}
menu.showMenu(true);
}
// Notify adapter that data has changed
mAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
hideDialog();
Toast.makeText(getActivity(), error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
AppController.getInstance().addToRequestQueue(request);
}
And here is the method where i'm loading first visible items when someone launch the app:
private void loadJokes(int page) {
pDialog.setMessage("Loading..");
showDialog();
StringRequest request = new StringRequest(Request.Method.GET, AppConfig.URL_GET_ALL_JOKES + page,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
mJokes.clear();
hideDialog();
try {
JSONObject object = new JSONObject(response);
boolean error = object.getBoolean("error");
JSONArray jokes = object.getJSONArray("jokes");
if (!error) {
for (int i = 0; i < jokes.length(); i++) {
JSONObject object1 = jokes.getJSONObject(i);
Joke joke = new Joke();
joke.setId(object1.optInt("id"));
joke.setLikes(object1.optInt("likes"));
joke.setComments(object1.optInt("comments"));
joke.setJoke(object1.optString("joke"));
joke.setCreatedAt(object1.optString("created_at"));
joke.setName(object1.optString("user_name"));
joke.setImagePath(object1.optString("image_path"));
joke.setFacebookUserId(object1.optString("facebook_user_id"));
joke.setCategory(object1.optString("category"));
mJokes.add(joke);
}
menu.showMenu(true);
}
// Notify adapter that data has changed
mAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
hideDialog();
menu.showMenu(true);
Toast.makeText(getActivity(), error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
AppController.getInstance().addToRequestQueue(request);
}
And this is onRefresh() method:
#Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
refreshItems();
}
}, 5000);
}
private void refreshItems() {
loadJokes(1);
mSwipeRefreshLayout.setRefreshing(false);
}
If i need to post more code, let me know. I really need to solve this problem as soon as i can. So again, the problems are the following:
When fast scrolling through the list, new items are being loaded, but immediately after that it returns me to the beginning of the list and when i go to the end of list again, load more doesn't respond.
After refreshing the list with SwipRefreshLayout, also scrolling doesn't respond at the end.
Note: The scrolling and loading new items is working only if i go slowly through the list and if i didn't swipe to refresh list.
EDIT:
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_jokes, container, false);
mContext = getActivity();
mView = (CoordinatorLayout) view.findViewById(R.id.coordinatorLayout);
TextView tvEmptyText = (TextView) view.findViewById(R.id.tv_empty);
ImageView ivSignal = (ImageView) view.findViewById(R.id.iv_signal);
if (!ConnectionDetector.getInstance(getActivity()).isOnline() && mAdapter == null) {
tvEmptyText.setVisibility(View.VISIBLE);
ivSignal.setVisibility(View.VISIBLE);
showNoInternetSnackbar();
}
// INITIALIZE RECYCLER VIEW
EmptyRecyclerView list = (EmptyRecyclerView) view.findViewById(R.id.list);
mJokes = new ArrayList<>();
mAdapter = new RecyclerJokesAdapter(getActivity(), mJokes, JokesFragment.this, null);
// Progress dialog
pDialog = new ProgressDialog(getActivity());
pDialog.setMessage("Please wait");
pDialog.setIndeterminate(true);
pDialog.setCancelable(false);
showDialog();
View emptyView = inflater.inflate(R.layout.layout_empty_view, container, false);
FloatingActionButton fab1 = (FloatingActionButton) view.findViewById(R.id.fab_funny);
FloatingActionButton fab2 = (FloatingActionButton) view.findViewById(R.id.fab_good_morning);
FloatingActionButton fab3 = (FloatingActionButton) view.findViewById(R.id.fab_good_night);
FloatingActionButton fab4 = (FloatingActionButton) view.findViewById(R.id.fab_all);
menu = (FloatingActionMenu) view.findViewById(R.id.menu_sort_jokes);
fab1.setOnClickListener(this);
fab2.setOnClickListener(this);
fab3.setOnClickListener(this);
fab4.setOnClickListener(this);
mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_container);
mSwipeRefreshLayout.setOnRefreshListener(this);
mSwipeRefreshLayout.setColorSchemeResources(
R.color.refresh_progress_1,
R.color.refresh_progress_2,
R.color.refresh_progress_3);
LinearLayoutManager manager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
list.setLayoutManager(manager);
list.setEmptyView(emptyView);
list.setItemAnimator(new DefaultItemAnimator());
list.setAdapter(mAdapter);
if (ConnectionDetector.getInstance(mContext).isOnline()) {
loadJokes(1);
} else {
showNoInternetSnackbar();
hideDialog();
}
list.addOnScrollListener(new EndlessRecyclerOnScrollListener(manager) {
#Override
public void onLoadMore(final int current_page) {
loadMoreJokes(current_page);
}
});
return view;
}
In onCreate method initialize your adapter, recyclerView and List
List<MyObject> myList = new ArrayList<>();
recyclerViewAdapter = new RecyclerViewAdapter(context, myList)
myRecyclerView.setAdapter(recyclerViewAdapter);
Now, whenever you load data. add the data to your myList and call notifyDataSetChange on your adpater
myList.add(data);
recyclerViewAdapter.notifyDataSetChange();
Use this wrapper class
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import java.util.List;
public abstract class RecyclerWrapperAdapter<E> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
protected Context context;
protected List<E> objects;
public void setContext(Context context) {
this.context = context;
}
public void setObjects(List<E> objects) {
this.objects = objects;
notifyDataSetChanged();
}
public void add(#NonNull E object) {
objects.add(object);
notifyDataSetChanged();
}
public void add(int position, #NonNull E object) {
if (position < objects.size() && position >= 0) {
objects.add(position, object);
notifyItemChanged(position);
notifyDataSetChanged();
} else if (position >= objects.size()) {
objects.add(object);
notifyDataSetChanged();
}
}
public void set(int position, #NonNull E object) {
if (position < objects.size() && position >= 0) {
objects.set(position, object);
notifyItemChanged(position);
} else if (position >= objects.size()) {
objects.add(object);
notifyDataSetChanged();
}
}
public void remove(#NonNull E object) {
objects.remove(object);
notifyDataSetChanged();
}
public void remove(int position) {
if (position >=0 && position < objects.size()) {
objects.remove(position);
notifyDataSetChanged();
}
}
public void removeAll() {
objects.clear();
notifyDataSetChanged();
}
public E getItem(int position) {
return objects.get(position);
}
#Override
public int getItemCount() {
return objects.size();
}
}
Well I have done this way:
MainActivity .java
public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener, onRecyclerViewListener {
private RecyclerView mRecyclerView;
private TextView tvEmptyView;
private LinearLayoutManager mLayoutManager;
private List<Object> studentList;
protected Handler handler;
private int count = 0;
private SwipeRefreshLayout swipeRefreshLayout;
private MyRecycleAdapter myRecycleAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
swipeRefreshLayout = (SwipeRefreshLayout)findViewById(R.id.swiperefresh);
swipeRefreshLayout.setOnRefreshListener(this);
swipeRefreshLayout.setColorSchemeResources(R.color.blue, R.color.purple, R.color.green, R.color.orange);
tvEmptyView = (TextView) findViewById(R.id.empty_view);
mRecyclerView = (RecyclerView)findViewById(R.id.recyclerView);
studentList = new ArrayList<Object>();
handler = new Handler();
loadData();
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
// use a linear layout manager
mRecyclerView.setLayoutManager(mLayoutManager);
myRecycleAdapter = new MyRecycleAdapter(mRecyclerView, studentList, R.layout.list_row, R.layout.progressbar_item, this);
myRecycleAdapter.setLoadMoreEnable(true);
myRecycleAdapter.setOnLoadMoreListener(new OnLoadMoreListener() {
#Override
public void onLoadMore() {
count++;
if (count == 4) {
count = 0;
myRecycleAdapter.setLoadMoreEnable(false);
} else {
myRecycleAdapter.setLoadMoreEnable(true);
}
//add null , so the adapter will check view_type and show progress bar at bottom
studentList.add(null);
myRecycleAdapter.notifyItemInserted(studentList.size() - 1);
handler.postDelayed(new Runnable() {
#Override
public void run() {
// remove progress item
studentList.remove(studentList.size() - 1);
myRecycleAdapter.notifyItemRemoved(studentList.size());
//add items one by one
int start = studentList.size();
int end = start + 20;
for (int i = start + 1; i <= end; i++) {
studentList.add(new Student("Student " + i, "AndroidStudent" + i + "#gmail.com"));
myRecycleAdapter.notifyItemInserted(studentList.size());
}
myRecycleAdapter.setLoaded();
//or you can add all at once but do not forget to call mAdapter.notifyDataSetChanged();
}
}, 1000);
}
});
ItemViewHolderNew.setRecyclerListener(this);
mRecyclerView.setAdapter(myRecycleAdapter);
if (studentList.isEmpty()) {
mRecyclerView.setVisibility(View.GONE);
tvEmptyView.setVisibility(View.VISIBLE);
} else {
mRecyclerView.setVisibility(View.VISIBLE);
tvEmptyView.setVisibility(View.GONE);
}
}
private void loadData() {
for (int i = 1; i <= 20; i++) {
studentList.add(new Student("Student " + i, "androidstudent" + i + "#gmail.com"));
}
}
#Override
public void onRefresh() {
swipeRefreshLayout.setRefreshing(true);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
swipeRefreshLayout.setRefreshing(false);
}
},5000);
}
#Override
public void onBindView(View view, final ItemViewHolderNew itemViewHolder) {
itemViewHolder.tvName = (TextView) view.findViewById(R.id.tvName);
itemViewHolder.tvEmailId = (TextView) view.findViewById(R.id.tvEmailId);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position, Object object, ItemViewHolderNew itemViewHolder) {
Student studentObj = (Student)object;
itemViewHolder.tvName.setText(studentObj.getName());
itemViewHolder.tvEmailId.setText(studentObj.getEmailId());
itemViewHolder.student= studentObj;
}
#Override
public void setClickListener(View view, ItemViewHolderNew itemViewHolder) {
Toast.makeText(view.getContext(), "OnClick :" + itemViewHolder.student.getName() + " \n " + itemViewHolder.student.getEmailId(), Toast.LENGTH_SHORT).show();
}
public static class ItemViewHolderNew extends RecyclerView.ViewHolder{
public TextView tvName, tvEmailId;
public Student student;
private static onRecyclerViewListener mListener;
public static void setRecyclerListener(onRecyclerViewListener listener){
mListener = listener;
}
public ItemViewHolderNew(View itemView) {
super(itemView);
mListener.onBindView(itemView, this);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setClick(v);
}
});
}
private void setClick(View v) {
mListener.setClickListener(v, this);
}
}
}
Add OnLoadMoreListener.java interface
public interface OnLoadMoreListener {
void onLoadMore();
}
Add Student.java as Model class
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String emailId;
public Student(String name, String emailId) {
this.name = name;
this.emailId = emailId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".MainActivity"
tools:showIn="#layout/activity_main">
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swiperefresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical">
</android.support.v7.widget.RecyclerView>
</android.support.v4.widget.SwipeRefreshLayout>
<TextView
android:id="#+id/empty_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="No Records Here !"
android:visibility="gone" />
</RelativeLayout>
list_row.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
android:padding="5dp"
android:background="?android:selectableItemBackground">
<TextView
android:id="#+id/tvName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="Name"
android:textColor="#android:color/black"
android:textSize="18sp" />
<TextView
android:id="#+id/tvEmailId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/tvName"
android:layout_margin="5dp"
android:text="Email Id"
android:textColor="#android:color/black"
android:textSize="12sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="Name"
android:textColor="#android:color/black"
android:textSize="18sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/tvName"
android:layout_margin="5dp"
android:text="Email Id"
android:textColor="#android:color/black"
android:textSize="12sp" />
</LinearLayout>
</android.support.v7.widget.CardView>
progressbar_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="center"
android:layout_width="match_parent" android:layout_height="match_parent">
<ProgressBar
android:id="#+id/progressBar1"
android:layout_width="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_height="wrap_content" />
</LinearLayout>
Working fine with Endless, swipe to refresh, load more RecyclerView.
Hope this would help you.
Volley RequestQueue uses a thread pool for network requests.
/** Number of network request dispatcher threads to start. */
private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 4;
Obviously, when you do fast scrolling through the list multiple requests are generated in quick succession.
There is a possibility that the responses are received asynchronously / out of sequence. Also, its possible that the "No more data" responses / error responses etc arrive before the responses with next page of data, which may lead to unexpected behaviour by your app.
Specially watch out for how this would effect your mJokes ArrayList member variable.