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.
Related
I have a problem, when i swipe to refresh the data, the first swipe is ok but after that every swipe reload and add the same data over and over again, by the end i have a list with same items over and over... I'm using a loader. I tried to clear before but i don't understand what's wrong with my code, if someone could explain it to me. Thank You.
Here my code :
public static final String EXTRA_URL = "imageUrl";
public static final String EXTRA_APKNAME = "apkname";
public static final String EXTRA_APKSIZE = "apksize";
public static final String EXTRA_APKFILE = "apkfile";
private RecyclerView mRecyclerView;
private MyAdapter mExampleAdapter;
private ArrayList<one_item> mExampleList;
private RequestQueue mRequestQueue;
private SwipeRefreshLayout swipeRefreshLayout;
#SuppressLint("RestrictedApi")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().setTitle("APK VIP CHINA");
getSupportActionBar().setDefaultDisplayHomeAsUpEnabled(true);
swipeRefreshLayout = findViewById(R.id.refreshlayout);
mRecyclerView = findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mExampleList = new ArrayList<>();
mRequestQueue = Volley.newRequestQueue(this);
parseJSON();
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
parseJSON();
swipeRefreshLayout.setRefreshing(false);
}
});
}
private void parseJSON() {
String url = "http://apkvip.net/json2.php";
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArray = response.getJSONArray("data");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject hit = jsonArray.getJSONObject(i);
String creatorName = hit.getString("ten");
String creatorsize = hit.getString("apk_size");
String creatorfile = hit.getString("link_apk");
String imageUrl = hit.getString("link_img");
mExampleList.add(new one_item(imageUrl, creatorName, creatorsize, creatorfile));
}
mExampleAdapter = new MyAdapter(MainActivity.this, mExampleList);
mRecyclerView.setAdapter(mExampleAdapter);
mExampleAdapter.setOnItemClickListener(MainActivity.this);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
mRequestQueue.add(request);
}
public void onItemClick(int position) {
Intent detailIntent = new Intent(this, activity_detail.class);
one_item clickedItem = mExampleList.get(position);
detailIntent.putExtra(EXTRA_URL, clickedItem.getmImageUrl());
detailIntent.putExtra(EXTRA_APKNAME, clickedItem.getMapkname());
detailIntent.putExtra(EXTRA_APKSIZE, clickedItem.getMapksize());
detailIntent.putExtra(EXTRA_APKFILE, clickedItem.getMapkfile());
startActivity(detailIntent);
}}
My adapter:
private ArrayList<one_item> mExampleList;
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onItemClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener) {
mListener = listener;
}
public MyAdapter(Context context, ArrayList<one_item> exampleList) {
mContext = context;
mExampleList = exampleList;
}
#Override
public ExampleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(mContext).inflate(R.layout.one_item, parent, false);
return new ExampleViewHolder(v);
}
#Override
public void onBindViewHolder(ExampleViewHolder holder, int position) {
one_item currentItem = mExampleList.get(position);
String imageUrl = currentItem.getmImageUrl();
String apkname = currentItem.getMapkname();
String apksize = currentItem.getMapksize();
String apkfile = currentItem.getMapkfile();
holder.mTextViewname.setText(apkname);
holder.mTextViewsize.setText(apksize);
holder.mTextViewfile.setText(apkfile);
Picasso.get().load(imageUrl).fit().centerInside().into(holder.mImageView);
}
#Override
public int getItemCount() {
return mExampleList.size();
}
#Override
public long getItemId(int position) {
return position;
}
public class ExampleViewHolder extends RecyclerView.ViewHolder {
public ImageView mImageView;
public TextView mTextViewname, mTextViewsize, mTextViewfile;
public ExampleViewHolder(View itemView) {
super(itemView);
mImageView = itemView.findViewById(R.id.image);
mTextViewname = itemView.findViewById(R.id.name);
mTextViewsize = itemView.findViewById(R.id.size);
mTextViewfile = itemView.findViewById(R.id.file);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mListener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
mListener.onItemClick(position);
}
}
}
});}}}
my activitymain.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:background="#FFFFFF"
android:orientation="vertical"
android:padding="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Recommended Apps"
android:textColor="#000"
android:textStyle="bold"
android:textSize="20sp"
android:layout_marginBottom="10dp"
/>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="#+id/refreshlayout"
android:layout_width="wrap_content"
android:layout_height="match_parent"
>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:padding="5dp" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
Just use mExampleList.clear() at the first line of your parseJSON() function
and then you'll be able to add the "updated" items.
In addition I'd suggest that you move swipeRefreshLayout.setRefreshing(false) to the end of Volley onResponse and onError() implementation -
Right now you're telling the swipeRefreshLayout to stop refreshing before the request(that happens asynchronously) has finished
You are initializing your adapter every time you do a swipe.
Change this constructor of MyAdapter code.
public MyAdapter(Context context, ArrayList<one_item> exampleList) {
mContext = context;
mExampleList = exampleList;
}
to,
public MyAdapter(Context context) {
mContext = context;
}
public setExampleList(ArrayList<one_item> exampleList){
mExampleList = exampleList;
}
Now change your onCreate function to.
#SuppressLint("RestrictedApi")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().setTitle("APK VIP CHINA");
getSupportActionBar().setDefaultDisplayHomeAsUpEnabled(true);
swipeRefreshLayout = findViewById(R.id.refreshlayout);
mRecyclerView = findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mExampleList = new ArrayList<>();
mRequestQueue = Volley.newRequestQueue(this);
//Changed Code
mExampleAdapter = new MyAdapter(MainActivity.this);
mRecyclerView.setAdapter(mExampleAdapter);
mExampleAdapter.setOnItemClickListener(MainActivity.this);
parseJSON();
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
parseJSON();
swipeRefreshLayout.setRefreshing(false);
}
});
}
private void parseJSON() {
String url = "http://apkvip.net/json2.php";
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArray = response.getJSONArray("data");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject hit = jsonArray.getJSONObject(i);
String creatorName = hit.getString("ten");
String creatorsize = hit.getString("apk_size");
String creatorfile = hit.getString("link_apk");
String imageUrl = hit.getString("link_img");
mExampleList.add(new one_item(imageUrl, creatorName, creatorsize, creatorfile));
}
//Changed Code
mExampleAdapter.setExampleList(mExampleList);
mExampleAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
mRequestQueue.add(request);
}
I have added a comment of the code block where I have made the changes.
Feel free to comment in case you have any queries.
Here is my Orderofday.java where i am getting data from URL and in String proceeding_file i get pdf link. i have shown the data present on every card but could not achieve to open a pdf link on card button clicked.
public class Orderofday extends AppCompatActivity {
private static final String TAG = Orderofday.class.getSimpleName();
private RecyclerView recyclerView;
private OrderList mAdapter;
ProgressDialog progess;
List<OrdersModel> myList = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_orderofday);
progess = new ProgressDialog(Orderofday.this);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mAdapter = new OrderList(myList, Orderofday.this);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
getResult();
}
public void getResult() {
String url = "http://senate.gov.pk/ne/getdata/order_of_day_json.php";
//detect internet and show the data
if (isNetworkStatusAvialable(getApplicationContext())) {
progess.setMessage("Loading data....");
progess.show();
StringRequest strReq = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d("response", response);
try {
JSONObject mainList = new JSONObject(response);
JSONArray result = mainList.getJSONArray("data");
if (result.length() > 0) {
for (int i = 0; i < result.length(); i++) {
mainList = result.getJSONObject(i);
OrdersModel model = new OrdersModel();
model.title_en = mainList.getString("title_en");
model.YearID = mainList.getString("YearID");
model.session_title_en = mainList.getString("session_title_en");
model.sitting_date = mainList.getString("sitting_date");
model.proceeding_file = mainList.getString("proceeding_file");
myList.add(model);
}
mAdapter.notifyDataSetChanged();
progess.dismiss();
} else {
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "Error: " + error.getMessage());
progess.dismiss();
}
});
Log.d("params", strReq.getUrl() + " and " + strReq.getBodyContentType() + " abd " + strReq.getBodyContentType());
// Adding String request to request queue
AppSingleton.getInstance(getApplicationContext()).addToRequestQueue(strReq, TAG);
} else {
Toast.makeText(getApplicationContext(), "Please check your Internet Connection", Toast.LENGTH_SHORT).show();
}
}
//check internet connection
public static boolean isNetworkStatusAvialable(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager != null) {
NetworkInfo netInfos = connectivityManager.getActiveNetworkInfo();
if (netInfos != null) {
return netInfos.isConnected();
}
}
return false;
}
}
Here is my OrderList.java class where i am setting the text from OderModel.java
public class OrderList extends RecyclerView.Adapter<OrderList.MyViewHolder> {
List<OrdersModel> list;
Context c;
public OrderList(List<OrdersModel> list, Context c) {
this.list = list;
this.c = c;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.orders_list, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
OrdersModel movie = list.get(position);
holder.name.setText(movie.gettitle_en());
holder.type.setText(movie.getYearID());
holder.session_title.setText((movie.getsession_title_en()));
holder.sitting_date.setText(movie.getsitting_date());
}
#Override
public int getItemCount() {
return list.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView name, type , session_title , sitting_date , proceeding_file;
public MyViewHolder(View view) {
super(view);
name = view.findViewById(R.id.name);
type = view.findViewById(R.id.type);
session_title = view.findViewById(R.id.session_title);
sitting_date = view.findViewById(R.id.sitting_date);
}
}
}
And here is my OrderModel.java where i made getters and setter
public class OrdersModel {
String title_en;
String YearID;
String session_title_en;
String sitting_date;
String proceeding_file;
public String gettitle_en() {
return title_en;
}
public void settitle_en(String title_en) {
this.title_en = title_en;
}
public String getYearID() {
return YearID;
}
public void setYearID(String YearID) {
this.YearID = YearID;
}
public String getsession_title_en() {
return session_title_en;
}
public void setsession_title_en(String session_title_en) {
this.session_title_en = session_title_en;
}
public String getsitting_date() {
return sitting_date;
}
public void setsitting_date(String session) {
this.sitting_date = sitting_date;
}
public String getproceeding_file() {
return proceeding_file;
}
public void setproceeding_file(String date) {
this.proceeding_file = proceeding_file;
}
String file;
}
Now i need to open a pdf against every card view clicked i got url of pdf in procedding_file (String) but couldn't get it. Kindly help me out to achieve this and here is xml.
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_margin="#dimen/_5sdp"
android:layout_height="wrap_content"
android:padding="10dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/name"
android:textStyle="bold"
android:textSize="20sp"
android:layout_margin="5dp"
android:text="Title_ID"
android:textColor="#android:color/black" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/type"
android:layout_below="#id/name"
android:layout_margin="5dp"
android:textSize="15sp"
android:text="YearID"
android:textColor="#android:color/black" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/session_title"
android:layout_below="#id/type"
android:layout_margin="5dp"
android:textSize="15sp"
android:text="Session Title"
android:textColor="#android:color/black" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/sitting_date"
android:layout_below="#id/session_title"
android:layout_margin="5dp"
android:textSize="15sp"
android:text="Date "
android:textColor="#android:color/black" />
<Button
android:id="#+id/view_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/sitting_date"
android:layout_alignParentRight="true"
android:text="Click to View Pdf"
android:textColor="#000000"
android:textSize="#dimen/_10sdp">
</Button>
<com.github.barteksc.pdfviewer.PDFView
android:id="#+id/pdfView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
</androidx.cardview.widget.CardView>
Above answer is correct. However a better solution and the rightest one is to create an interface for the clicklistenet and implement it in tour activity
Initialize viewButton in ViewHolder.
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView name, type , session_title , sitting_date , proceeding_file;
public Button viewButton;
public MyViewHolder(View view) {
super(view);
name = view.findViewById(R.id.name);
type = view.findViewById(R.id.type);
session_title = view.findViewById(R.id.session_title);
sitting_date = view.findViewById(R.id.sitting_date);
viewButton = view.findViewById(R.id.view_button);
}
}
Then set onClickListener on viewButton and openPdf
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
OrdersModel movie = list.get(position);
holder.name.setText(movie.gettitle_en());
holder.type.setText(movie.getYearID());
holder.session_title.setText((movie.getsession_title_en()));
holder.sitting_date.setText(movie.getsitting_date());
holder.viewButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openPdf(movie.getproceeding_file())
}
});
}
Suggestion: You should move your PdfViewer in another activity and redirect user to that activity when click viewButton.
initialise view_pdf button in MyViewHolder class. like others.
parse proceeding file like others ~ movie.getproceeding_file()
under the onBindViewHolder put below snippet of code:
holder.proceeding_file.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String pdf_url = movie.getproceeding_file();
// do not forget to concate preceding url of the pdf
Webview webView = (WebView) findViewById(R.id.webView1);
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl(pdf_url);
}
});
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 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();