How to load more data in Recyclerview in android - android

I am using recyclerview in which I want to fetch more data from server using json.
scenario is something like that :- On first hit I want to display 5 page in list and a show more button below recyclerview is there when user click show more button on second hit display 5 more pages.how can I do that
here is my init():
public void init() {
mProgressBar = (ProgressBar) m_Main.findViewById(R.id.progressBar1);
mProgressBar.setVisibility(View.GONE);
m_showMore = (AppCompatButton) m_Main.findViewById(R.id.show_more);
m_showMore.setBackgroundColor(Color.TRANSPARENT);
m_showMore.setVisibility(View.GONE);
// Getting the string array from strings.xml
m_n_FormImage = new int[]{
R.drawable.amazon,
R.drawable.whatsapp,
R.drawable.zorpia,
R.drawable.path,
R.drawable.app_me,
R.drawable.evernote,
R.drawable.app_me};
m_RecyclerView = (RecyclerView) m_Main.findViewById(R.id.my_recycler_view);//finding id of recyclerview
m_RecyclerView.setItemAnimator(new DefaultItemAnimator());//setting default animation to recyclerview
m_RecyclerView.setHasFixedSize(true);//fixing size of recyclerview
mLayoutManager = new LinearLayoutManager(getActivity());
m_RecyclerView.setLayoutManager(mLayoutManager);//showing odata vertically to user.
sz_RecordCount = String.valueOf(m_n_DefaultRecordCount);// increment of record count
sz_LastCount = String.valueOf(m_n_DeafalutLastCount);// increment of last count...
m_Handler = new Handler();
}
public void implementScroll() {// on scroll load more data from server.............
m_RecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
}
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dy > 0) {
m_showMore.setVisibility(View.VISIBLE);
m_showMore.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//change boolean value
m_showMore.setVisibility(View.GONE);
m_n_DefaultRecordCount = m_n_DefaultRecordCount + 5;// increment of record count by 5 on next load data
m_n_DeafalutLastCount = m_n_DeafalutLastCount + 5;// same here.....as above
sz_RecordCount = String.valueOf(m_n_DefaultRecordCount);// convert int value to string
sz_LastCount = String.valueOf(m_n_DeafalutLastCount);// convert int value to string /////
new DealNext().execute(m_DealListingURL);// POST DATA TO SERVER TO LOAD MORE DATA......
}
});
} else {
m_showMore.setVisibility(View.GONE);
}
}
});
}
here is my first serevr hit:-
//sending deal data to retreive response from server
public String DealListing(String url, CRegistrationDataStorage login) {
InputStream inputStream = null;
m_oJsonsResponse = new CJsonsResponse();
try {
// 1. create HttpClient
HttpClient httpclient = new DefaultHttpClient();
// 2. make POST request to the given URL
HttpPost httpPost = new HttpPost(url);
String json = "";
// 3. build jsonObject
JSONObject jsonObject = new JSONObject();
jsonObject.put("agentCode", m_szMobileNumber);
jsonObject.put("pin", m_szEncryptedPassword);
jsonObject.put("recordcount", sz_RecordCount);
jsonObject.put("lastcountvalue", sz_LastCount);
//jsonObject.put("emailId", "nirajk1190#gmail.com");
// 4. convert JSONObject to JSON to String
json = jsonObject.toString();
// 5. set json to StringEntity
StringEntity se = new StringEntity(json);
// 6. set httpPost Entity
httpPost.setEntity(se);
// 7. Set some headers to inform server about the type of the content
httpPost.setHeader("Content-type", "application/json");
// 8. Execute POST request to the given URL
HttpResponse httpResponse = httpclient.execute(httpPost);
HttpEntity entity = httpResponse.getEntity();
// 9. receive response as inputStream
inputStream = entity.getContent();
System.out.println("InputStream....:" + inputStream.toString());
System.out.println("Response....:" + httpResponse.toString());
StatusLine statusLine = httpResponse.getStatusLine();
System.out.println("statusLine......:" + statusLine.toString());
////Log.d("resp_body", resp_body.toString());
int statusCode = statusLine.getStatusCode();
// 10. convert inputstream to string
if (statusCode == 200) {
// 10. convert inputstream to string
if (inputStream != null)
s_szresult = m_oJsonsResponse.convertInputStreamToString(inputStream);
//String resp_body =
EntityUtils.toString(httpResponse.getEntity());
} else
s_szresult = "Did not work!";
} catch (Exception e) {
Log.d("InputStream", e.getLocalizedMessage());
}
System.out.println("resul.....:" + s_szresult);
// 11. return s_szResult
return s_szresult;
}
public void getResponse() throws JSONException {// getting response from serevr ..................
if (m_oResponseobject.getString("resultdescription").equalsIgnoreCase("Transaction Successful")) {// server based condition
m_oAdapter = new CDealAppListingAdapter(s_oDataset);// create adapter object and add arraylist to adapter
m_oAdapter.notifyDataSetChanged();
m_RecyclerView.setAdapter(m_oAdapter);//adding adapter to recyclerview
} else if (m_oResponseobject.getString("resultdescription").equalsIgnoreCase("Connection Not Available")) {//server based conditions
CToastMessage.getInstance().showToast(getActivity(), "Connection not avaliable");
} else if (m_oResponseobject.getString("resultdescription").equalsIgnoreCase("Deal List Not Found")) {// serevr based conditions .....
CToastMessage.getInstance().showToast(getActivity(), "No More Deals Available");
}
}
// sending deal data to server and retreive response......
class CDealDataSent extends AsyncTask<String, Void, String> {
public CRegistrationDataStorage oRegisterStorage;
public CDealAppDatastorage item;
#Override
protected void onPreExecute() {
super.onPreExecute();
CProgressBar.getInstance().showProgressBar(getActivity(), "Please wait while Loading Deals...");
}
#Override
protected String doInBackground(String... urls) {
return DealListing(urls[0], oRegisterStorage);// sending data to server...
}
// onPostExecute displays the results of the AsyncTask.
#Override
protected void onPostExecute(final String result) {
new Thread(new Runnable() {
#Override
public void run() {
m_Handler.post(new Runnable() {
#Override
public void run() {
CProgressBar.getInstance().hideProgressBar();// hide progress bar after getting response from server.......
try {
m_oResponseobject = new JSONObject(result);// getting response from server
JSONArray posts = m_oResponseobject.optJSONArray("dealList");
s_oDataset = new ArrayList<CDealAppDatastorage>();
for (int i = 0; i < posts.length(); i++) {
JSONObject post = posts.getJSONObject(i);
item = new CDealAppDatastorage();
item.setM_szHeaderText(post.getString("dealname"));
item.setM_szsubHeaderText(post.getString("dealcode"));
item.setM_n_Image(m_n_FormImage[i]);
s_oDataset.add(item);
}
getResponse();
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
}).start();
}
}
here is my second serevr hit
// sending data and receive reponse on second hit T LOAD MORE DATA when show more Btn clicked..............
private class DealNext extends AsyncTask<String, Void, String> {
public CRegistrationDataStorage oRegisterStorage;
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressBar.setVisibility(View.VISIBLE);// SHOW PROGRESS BAR
}
#Override
protected String doInBackground(String... urls) {
//My Background tasks are written here
synchronized (this) {
return DealListing(urls[0], oRegisterStorage);// POST DATA TO SERVER
}
}
#Override
protected void onPostExecute(final String result) {
super.onPostExecute(result);
new Thread(new Runnable() {
#Override
public void run() {
m_Handler.post(new Runnable() {
#Override
public void run() {
mProgressBar.setVisibility(View.INVISIBLE);// DISMISS PROGRESS BAR..........
try {
m_oResponseobject = new JSONObject(result);// getting response from server
final JSONArray posts = m_oResponseobject.optJSONArray("dealList");// GETTING DEAL LIST
for (int i = 0; i < posts.length(); i++) {
JSONObject post = posts.getJSONObject(i);// GETTING DEAL AT POSITION AT I
item = new CDealAppDatastorage();// object create of DealAppdatastorage
item.setM_szHeaderText(post.getString("dealname"));//getting deal name
item.setM_szsubHeaderText(post.getString("dealcode"));// getting deal code
item.setM_n_Image(m_n_FormImage[i]);// static image for testing purpose not original....
s_oDataset.add(item);// add items to arraylist....
m_oAdapter.notifyItemInserted(s_oDataset.size());// notify adapter when deal added to recylerview
}
getResponse();// getting response from server.....and also here response based logics...
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
}).start();
}
}
here is my adapter class:
public class CDealAppListingAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static CDealAppDatastorage list;
private static ArrayList<CDealAppDatastorage> s_oDataset;
private final int VIEW_TYPE_ITEM = 0;
private final int VIEW_TYPE_LOADING = 1;
public CDealAppListingAdapter(ArrayList<CDealAppDatastorage> mDataList) {
s_oDataset = mDataList;
}
#Override
public int getItemViewType(int position) {
return s_oDataset.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
if (i == VIEW_TYPE_ITEM) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.deallisting_card_view, viewGroup, false);
return new DealAppViewHolder(view);
} else if (i == VIEW_TYPE_LOADING) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_loading_item, viewGroup, false);
return new LoadingViewHolder(view);
}
return null;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof DealAppViewHolder) {
list = s_oDataset.get(position);// receiving item on position on index i
DealAppViewHolder dealAppViewHolder = (DealAppViewHolder) holder;
dealAppViewHolder.s_szAppImage.setImageResource(list.getM_n_Image());
dealAppViewHolder.s_szheadingText.setText(list.getM_szHeaderText());
dealAppViewHolder.s_szSubHeader.setText(list.getM_szsubHeaderText());
} else if (holder instanceof LoadingViewHolder) {
LoadingViewHolder loadingViewHolder = (LoadingViewHolder) holder;
loadingViewHolder.progressBar.setIndeterminate(true);
}
}
#Override
public int getItemCount() {
return (s_oDataset == null ? 0 : s_oDataset.size());//counting size of odata in ArrayList
}
static class LoadingViewHolder extends RecyclerView.ViewHolder {
public ProgressBar progressBar;
public LoadingViewHolder(View itemView) {
super(itemView);
progressBar = (ProgressBar) itemView.findViewById(R.id.progressBar1);
}
}
public static class DealAppViewHolder extends RecyclerView.ViewHolder {
public static ImageView s_szAppImage;
public static TextView s_szheadingText, s_szSubHeader;
public static Button s_szGetDealBtn;
public DealAppViewHolder(View itemLayoutView) {
super(itemLayoutView);
s_szheadingText = (TextView) itemLayoutView.findViewById(R.id.headingText);// finding id of headerText...
s_szSubHeader = (TextView) itemLayoutView.findViewById(R.id.subHeaderText);// finding id of subHeader.....
s_szAppImage = (ImageView) itemLayoutView.findViewById(R.id.appImage);//finding Id of Imgae in CardView
s_szGetDealBtn = (Button) itemLayoutView.findViewById(R.id.getDealBtn);// finding id of getdeal Btn
Random rnd = new Random();//creating object of Random class
int color = Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));//genrating random color
s_szGetDealBtn.setBackgroundColor(color);//backgraound color of getDeal Btn
s_szGetDealBtn.setOnClickListener(new View.OnClickListener() {// onclick getDeal Btn
#Override
public void onClick(View v) {//send to deal detail page onclick getDeal Btn
Intent i = new Intent(v.getContext(), CDealAppListingDetails.class);
i.putExtra("DealCode", s_oDataset.get(getPosition()).getM_szsubHeaderText());
i.putExtra("headerText", s_oDataset.get(getPosition()).getM_szHeaderText());
v.getContext().startActivity(i);
}
});
itemLayoutView.setOnClickListener(new View.OnClickListener() {// onclick cardview
#Override
public void onClick(View v) {// onclick cardview send to deal app listing details page .....
Intent i = new Intent(v.getContext(), CDealAppListingDetails.class);
i.putExtra("DealCode", list.getM_szsubHeaderText());
i.putExtra("headerText", list.getM_szHeaderText());
v.getContext().startActivity(i);
}
});
}
}
}

Either store two lists in your adapter, the currently displayed list and the full list, or get only the content you need if your API allows it.
You can then set your adapter size in getItemCount to be your displayed list size + 1 (for the view more items). You will need to add a separate view type to return in getItemViewType for your view more cell (the logic to display it would be if the position is currently displayed list size). You will also need to add a new view and view holder for the load more cell.
After you've set up your new view more cell you can simply add a click listener to it, if clicked add 5 items from your full list into your currently displayed list (making sure to start at the currently displayed list - 1 index of the full list, and call notifyDataSetChanged, or notifyItemAdded x 5.
I'm sorry I currently don't have time to write an appropriate adapter for you but I hope the above explanation will suffice.

Related

ListView doesn't refresh with notifydatasetchanged

I have a MySQL database of two columns displayed in an android ListView. I use Retrofit 1.9 to get the data from MySQL. The adapter for the ListView is a BaseAdapter and I don't have a DatabaseHelperclass. When I add a data in the ListView from my mobile phone, it doesn't refresh the ListView. I have to close and restart the app. I try to refresh with listViewAdapter.notifyDataSetChanged();.
This is the fragment where the listview is:
public class rightFragment extends Fragment {
String BASE_URL = "http://awebsite.com";
View view;
ListView listView;
ListViewAdapter listViewAdapter;
Button buttondisplay;
Button buttonadd;
EditText new_id;
EditText newWordFra;
EditText newWordDeu;
ArrayList<String> id = new ArrayList<>();
ArrayList<String> fra = new ArrayList<>();
ArrayList<String> deu = new ArrayList<>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(com.example.geeko.Deu.R.layout.fragment_right, container, false);
listView = (ListView) view.findViewById(com.example.geeko.Deu.R.id.listView); //<<<< ADDED NOTE use your id
listViewAdapter = new ListViewAdapter(getActivity(), id, fra, deu);
displayData();
buttondisplay = (Button) view.findViewById(com.example.geeko.Deu.R.id.buttondisplay);
buttonadd = (Button) view.findViewById(com.example.geeko.Deu.R.id.buttonadd);
buttondelete = (Button) view.findViewById(com.example.geeko.Deu.R.id.newID);
newWordFra = (EditText) view.findViewById(com.example.geeko.Deu.R.id.newWordFra);
newWordDeu = (EditText) view.findViewById(com.example.geeko.Deu.R.id.newWordDeu);
buttonadd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Toast.makeText(MainActivity.this , "button add", Toast.LENGTH_LONG).show();
insert_data();
listViewAdapter.notifyDataSetChanged();
}
});
buttondisplay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (buttondisplay.getText().toString().contains("Show")) {
listView.setAdapter(listViewAdapter);
buttondisplay.setText("Hide");
} else {
listView.setAdapter(null);
buttondisplay.setText("Show");
}
}
});
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long ids) {
new_id.setText(id.get(position));
newWordFra.setText(fra.get(position));
newWordDeu.setText(deu.get(position));
}
});
return view;
}
public void insert_data() {
RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(BASE_URL) //Setting the Root URL
.build();
AppConfig.insert api = adapter.create(AppConfig.insert.class);
api.insertData(
newWordFra.getText().toString(),
newWordDeu.getText().toString(),
new Callback<Response>() {
#Override
public void success(Response result, Response response) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(result.getBody().in()));
String resp;
resp = reader.readLine();
Log.d("success", "" + resp);
JSONObject jObj = new JSONObject(resp);
int success = jObj.getInt("success");
if(success == 1){
Toast.makeText(getActivity(), "Successfully inserted", Toast.LENGTH_SHORT).show();
} else{
Toast.makeText(getActivity(), "Insertion Failed", Toast.LENGTH_SHORT).show();
}
} catch (IOException e) {
Log.d("Exception", e.toString());
} catch (JSONException e) {
Log.d("JsonException", e.toString());
}
}
#Override
public void failure(RetrofitError error) {
Toast.makeText(getActivity(), error.toString(), Toast.LENGTH_LONG).show();
}
}
);
}
public void displayData() {
RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(BASE_URL) //Setting the Root URL
.build();
AppConfig.read api = adapter.create(AppConfig.read.class);
api.readData(new Callback<JsonElement>() {
#Override
public void success(JsonElement result, Response response) {
String myResponse = result.toString();
Log.d("response", "" + myResponse);
try {
JSONObject jObj = new JSONObject(myResponse);
int success = jObj.getInt("success");
if (success == 1) {
JSONArray jsonArray = jObj.getJSONArray("details");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jo = jsonArray.getJSONObject(i);
id.add(jo.getString("id"));
fra.add(jo.getString("fra"));
deu.add(jo.getString("deu"));
}
listView.setAdapter(listViewAdapter);
} else {
Toast.makeText(getActivity(), "No Details Found", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
Log.d("exception", e.toString());
}
}
#Override
public void failure(RetrofitError error) {
Log.d("Failure", error.toString());
Toast.makeText(getActivity(), error.toString(), Toast.LENGTH_LONG).show();
}
}
);
}
}
This is the listViewAdpater class :
public class ListViewAdapter extends BaseAdapter {
private final Context context;
private ArrayList<String> id = new ArrayList<String>();
private ArrayList<String> fra = new ArrayList<String>();
private ArrayList<String> deu = new ArrayList<String>();
LayoutInflater layoutInflater;
public ListViewAdapter(Context ctx, ArrayList<String> id, ArrayList<String> fra, ArrayList<String> deu) {
this.context = ctx;
this.id = id;
this.fra = fra;
this.deu = deu;
}
#Override
public int getCount() {
return id.size();
}
#Override
public Object getItem(int position) {
return id.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#SuppressLint("ViewHolder")
#Override
public View getView(final int position, View view, ViewGroup parent) {
final Holder holder;
if (view == null) {
layoutInflater = (LayoutInflater) context.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
view = layoutInflater.inflate(R.layout.list_item, null);
holder = new Holder();
holder.txt_fra = (TextView) view.findViewById(R.id.fra);
holder.txt_deu = (TextView) view.findViewById(R.id.deu);
view.setTag(holder);
} else {
holder = (Holder) view.getTag();
}
holder.txt_fra.setText(fra.get(position));
holder.txt_deu.setText(deu.get(position));
return view;
}
static class Holder {
TextView txt_fra, txt_deu;
}
}
Should I create a method to refresh my ListView?
First of all I would suggest to remove the unnecessary initialization of your variables inside the Adapter:
private ArrayList<String> id = new ArrayList<String>();
private ArrayList<String> fra = new ArrayList<String>();
private ArrayList<String> deu = new ArrayList<String>();
By assigning the pointer from your fragment you will already assign an initialized ArrayList. You want both pointers to point at the same ArrayList Object so changes apply to both.
Apparently, the data stored in the Adapter is not being updated correctly. I would suggest to debug your app - setting the breakpoint so that you can see the data that the Adapter stores after an update.
The idea of writing a method for updates has already been implemented with the notifyDataSetChanged(). Just override the method in your adapter and do eventual changes before calling the super.notifyDataSetChanged().
If you have any success with those changes let us know.
buttonadd.setOnClickListener(new View.OnClickListener() {
...
insert_data();
listViewAdapter.notifyDataSetChanged();
}
});
In your onClickListener, you are calling insert_data(), followed by listViewAdapter.notifyDataSetChanged()
insert_data() method is sending a network request to retrieve the data to populate the list. BUT, you are calling notifyDataSetChanged BEFORE the network request is done. That's why the listView is empty, and will stay empty. You need to wait AFTER the network request and AFTER you have populated your ArrayList with the data to call notifyDataSetChanged.
How do we know the network request is done? Simply at the end of the callback (which you've implemented):
new Callback<Response>() {
#Override
public void success(Response result, Response response) {...
At the end of the success method, you call listViewAdapter.notifyDataSetChanged() method.
Hope that makes sense! Try it and let us know what happens
I've founded a solution. I've added getActivity.recreate(); in the method insert_data.
public void success(Response result, Response response) {
try {
BufferedReader reader = new BufferedReader
(new InputStreamReader(result.getBody().in()));
String resp;
resp = reader.readLine();
Log.d("success", "" + resp);
JSONObject jObj = new JSONObject(resp);
int success = jObj.getInt("success");
if(success == 1){
Toast.makeText(getActivity(), "Successfully inserted",
Toast.LENGTH_SHORT).show();
getActivity().recreate();
} else{
Toast.makeText(getActivity(), "Insertion Failed",
Toast.LENGTH_SHORT).show();
}
} catch (IOException e) {
Log.d("Exception", e.toString());
} catch (JSONException e) {
Log.d("JsonException", e.toString());
}
}
I'm not sure that is the best solution but it works.

RecyclerView chat load more items from top

I am trying to implement pagination in recyclerview to load more chat messages when the user scrolls to top , this is achieved by sending the last message time i.e coversations[0] time to the API , but when the new list is added the old List gets repeated many times . I think this is because i am not updating the time properly , What is the correct way to achieve this?
This is the code i am using, first time i am setting the flag to false and time as empty.
getConvoData(k, " ", "", false);
private String last_msg_time = " ";
private Boolean flag = false;
rv_convo.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (!recyclerView.canScrollVertically(-1)) {
if (conversations != null) {
String time = last_msg_time;
getConvoData(k, " ", time, true);
}
}
}
});
this is the method for fetching conversation Data
private void getConvoData(final String k, final String new_message, final String last_time, final boolean flag) {
final String token1 = Global.shared().tb_token;
final String url = "https://app.aer.media/v2/message_router/_getChat";
final JSONObject jsonBody = new JSONObject();
final ProgressDialog progressDialog = new ProgressDialog(this);
final String mRequestBody = jsonBody.toString();
StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new com.android.volley.Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jObj = new JSONObject(response);
final JSONObject data = jObj.getJSONObject("data");
conversations = data.getJSONArray("conversation");
JSONObject for_chat = data.getJSONObject("for_chat");
JSONArray jsonArr_chat = new JSONArray();
jsonArr_chat.put(for_chat);
params = (RelativeLayout.LayoutParams) rv_convo.getLayoutParams();
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
if (!flag) {
convobeans = gson.fromJson(conversations.toString(), convType);
last_msg_time = conversations.getJSONObject(0).getString("time");
Log.d("OldList", convobeans.toString());
adapter = new ChatDetailsAdapter(forChatBeen, convobeans, ChatDetailsActivity.this, forChatBeansList, image, name, initials, new_message, bitmap);
// Collections.reverse(convobeans);
rv_convo.setAdapter(adapter);
rv_convo.smoothScrollToPosition( rv_convo.getAdapter().getItemCount() - 1);
adapter.notifyDataSetChanged();
rv_convo.setNestedScrollingEnabled(true);
} else {
newConvo = gson.fromJson(conversations.toString(), convType);
last_msg_time = conversations.getJSONObject(0).getString("time");
if (newConvo != null && newConvo.size() > 0) {
Log.d("newList", newConvo.toString());
convobeans.addAll(0, newConvo);
adapter.notifyItemChanged(0, newConvo.size());
}
}
}
}
}
Depending on the flag I am updating the list and updating the time as well but the list gets repeated in the RecyclerView due to the previous time being passed , how do I update the time optimally and fetch the new list each time?
This code is used to fetch the data when the user scroll down in a recylerview. Just analyze this code you will get the basic idea.
rvCategory.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (dy > 0) {
visibleItemCount = mLinearLayoutManager.getChildCount();
totalItemCount = mLinearLayoutManager.getItemCount();
pastVisiblesItems = mLinearLayoutManager.findFirstVisibleItemPosition();
if (loading) {
if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
loading = false;
fetchData();
}
}
}
}
});
Function FetchData()
private void fetchData() {
String url = EndPoints.location + "getMobileData.php?lastData=" + lastData;
JsonObjectRequest jsObjRequest = new JsonObjectRequest
(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
lastData = response.getString("last");
JSONArray jArray = response.getJSONArray("response");
if (jArray.length() == 0) {
//Empty condition
} else {
for (int i = 0; i < jArray.length(); i++) {
//Append the chat with the Dataobject of your modelAnd swap the recylerview view with new data
//Example
}
adapter.swap(rvHomeModel.createHomeList(DataPathsHome, true));
}
} catch (JSONException e) {
e.printStackTrace();
}
loading = true;
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
loading = true;
Toast.makeText(CategoryView.this, "No internet connection", Toast.LENGTH_LONG).show();
}
});
// Add a request (in this example, called stringRequest) to your RequestQueue.
MySingleton.getInstance(this).addToRequestQueue(jsObjRequest);
}
Create a function called swap in your adapter class that accept the new dataset
public void swap(List<rvHomeModel> list) {
//Check your previouse dataset used in adapter is empty or not
if (rvHomeModels!= null) {
rvHomeModels.clear();
rvHomeModels.addAll(list);
} else {
rvHomeModels = list;
}
notifyDataSetChanged();
}
At server
1. Get the previous value
2. Do the database operation and get the chats id < of previous
2. Create a JSON Object contain
{
last:last_chat_id,
response:{
//Your chat
}
}
This is not a perfect solution for this question. But you will get the basic idea about what you are looking for.

android recyclerview load more item upon scrolling using volley

Please help me out to load more data from the server upon scrolling my RecyclerView . Here I have successfully created RecyclerView by loading data from my Mysql server by using volley string request.
Here is my code.
private void populateRecycleView() {
if (Utility.checkNetworkConnection(this)) {
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setTitle("Searching...");
progressDialog.setMessage("Searching for the blood donor. Please wait a moment.");
progressDialog.setCancelable(false);
progressDialog.show();
StringRequest stringRequest = new StringRequest(Request.Method.POST, Constants.GET_DONORS_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
progressDialog.dismiss();
try {
JSONArray jsonArray = new JSONArray(response);
int count = 0;
while (count < jsonArray.length()) {
JSONObject jsonObject = jsonArray.getJSONObject(count);
String firstName = jsonObject.getString("fName");
String secondName = jsonObject.getString("sName");
String email = jsonObject.getString("emailid");
String password = jsonObject.getString("pass");
String mobile = jsonObject.getString("mobile");
String bloodRt = jsonObject.getString("blood");
String age = jsonObject.getString("age");
String gender = jsonObject.getString("gender");
String country = jsonObject.getString("country");
String location = jsonObject.getString("location");
String latitude = jsonObject.getString("latitude");
String longitude = jsonObject.getString("longitude");
String profilePicFIleName = jsonObject.getString("picname");
String profilePicURL = jsonObject.getString("pic");
Donor donor = new Donor(firstName, secondName, email, password, mobile, bloodRt, age, gender,
country, location, latitude, longitude, profilePicFIleName, profilePicURL);
donorsList.add(donor);
count++;
}
donorsAdapter = new DonorsAdapter(FindDonorResult.this, donorsList);
recyclerView = (RecyclerView) findViewById(R.id.rv_search_result_donor);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(FindDonorResult.this));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(donorsAdapter);
donorsAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
progressDialog.dismiss();
Toast.makeText(FindDonorResult.this, "Active data network is not available.", Toast.LENGTH_LONG).show();
}
}
) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("bloodGroup", bloodGroup);
return params;
}
};
NetworkRequestSingleTon.getOurInstance(this).addToRequestQue(stringRequest);
} else {
Utility.checkNetworkConnectionFound(this);
}
}
And this is my RecyclerView adapter...
public class DonorsAdapter extends RecyclerView.Adapter<DonorsAdapter.CustomViewHolder> {
private Context context;
private ArrayList<Donor> donorList;
private String bloodGroup;
public DonorsAdapter(Context context, ArrayList<Donor> donorList) {
this.context = context;
this.donorList = donorList;
}
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rv_blood_donors_result,
parent, false);
return new CustomViewHolder(view);
}
#Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
final Donor donor = donorList.get(position);
String displayName = donor.getFirstName() + " " + donor.getSecondName();
holder.tvDisplayName.setText(displayName);
holder.tvEmailID.setText(donor.getEmail());
String userProfileURL = donor.getProfilePicURL();
if (!userProfileURL.equals("")) {
Picasso.with(context).load(userProfileURL).resize(80, 80).centerCrop().
into(holder.ivProfilePic);
} else {
holder.ivProfilePic.setImageResource(R.drawable.ic_person_white_24dp);
}
bloodGroup = donor.getBloodGroup();
if (bloodGroup.equals("A+"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.a_);
else if (bloodGroup.equals("A-"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.a_negative);
else if (bloodGroup.equals("B+"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.b_positive);
else if (bloodGroup.equals("B-"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.b_negative);
else if (bloodGroup.equals("O+"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.o_positive);
else if (bloodGroup.equals("O-"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.o_negative);
else if (bloodGroup.equals("AB+"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.ab_positive);
else if (bloodGroup.equals("AB-"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.ab_negative);
if(Utility.isNetworkEnabled){
holder.constraintLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, DisplayDonorDetails.class);
intent.putExtra("donor", donor);
context.startActivity(intent);
}
});
}else {
Toast.makeText(context, "Network not available.", Toast.LENGTH_SHORT).show();
}
}
#Override
public int getItemCount() {
if(donorList != null){
return donorList.size();
}else {
return 0;
}
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
ImageView ivProfilePic, ivBloodTypeDisplay, ivArrow;
TextView tvDisplayName;
TextView tvEmailID;
ConstraintLayout constraintLayout;
public CustomViewHolder(View itemView) {
super(itemView);
ivProfilePic = (ImageView) itemView.findViewById(R.id.civ_user_profile_picture);
ivBloodTypeDisplay = (ImageView) itemView.findViewById(R.id.civ_user_blood_type_display);
ivArrow = (ImageView) itemView.findViewById(R.id.civ_arrow);
tvDisplayName = (TextView) itemView.findViewById(R.id.tvUserNameOnRV);
tvEmailID = (TextView) itemView.findViewById(R.id.tvEmailDisplayOnRV);
constraintLayout = (ConstraintLayout) itemView.findViewById(R.id.recycle_view_item_container);
}
}
}
Populate your donorsAdapter only with the 50 first elements of your donorsList, create a function that save the position of the latest element displayed and add other 50 donors to your adapter starting from the latest position saved when you need it.
Hope it helps.
EDIT
First create an emptyList:
List<Donor> subElements = new ArrayList<>();
and pass it to your adapter:
donorsAdapter = new DonorsAdapter(FindDonorResult.this, subElements);
Now you can create a method like this (you can call in onClick event for example):
private int LAST_POSITION = 0;
private int DONORS_NUM_TOSHOW = 50;
public void showMoreDonors(){
if(donarsList.size() > Last_postion+50){
List<Donor> tempList = new ArrayList<Donor>(donorsList.subList(Last_postion,Last_postion+DONORS_NUM_TOSHOW));
for(Donor a : tempList){
subElements.add(a);
}
Last_postion += DONORS_NUM_TOSHOW;
donorsAdapter.notifyDataSetChanged();
}else{
List<Donor> tempList = new ArrayList<Donor>(donorsList.subList(Last_postion,donorsList.size()));
for(Donor a : tempList){
subElements.add(a);
}
donorsAdapter.notifyDataSetChanged();
}
}
Remember to check when donorsList is over.
I didn't test it, but i hope it is usefull to understand the idea.
Finally, I sort this out. I have got an awesome tutorial from this blog.
http://android-pratap.blogspot.in/2015/06/endless-recyclerview-with-progress-bar.html.
I made some changes to populate the list because my data is on a remote server and by using volley library I fetched the data into the list. Remaining things are same.

How to make progress dialog in fragment tab in Android?

I have MainActivity which added two fragment tab namely "tab1 and "tab2.tab 1 sends some request to server during this process I Want to show a progress dialog but when I do this through a error message "android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application" and also have some implementation of Broadcast receiver in tab 1 fragment which also through error "unable to register receiver"
Progress dialog code:
public class DialogUtils {
public static ProgressDialog showProgressDialog(Context context, String message) {
ProgressDialog m_Dialog = new ProgressDialog(context);
m_Dialog.setMessage(message);
m_Dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
m_Dialog.setCancelable(false);
m_Dialog.show();
return m_Dialog;
}
}
Mainactivity code:
m_TabLayout = (TabLayout) findViewById(R.id.tab_layout);// finding Id of tablayout
m_ViewPager = (ViewPager) findViewById(R.id.pager);//finding Id of ViewPager
m_TabLayout.addTab(m_TabLayout.newTab().setText("Deals"));// add deal listin tab
m_TabLayout.addTab(m_TabLayout.newTab().setText("Stories"));
m_TabLayout.setTabGravity(TabLayout.GRAVITY_FILL);// setting Gravity of Tab
CDealMainListingPager m_oDealMainScreenPager = new CDealMainListingPager(getSupportFragmentManager(), m_TabLayout.getTabCount());
m_ViewPager.setAdapter(m_oDealMainScreenPager);// adiing adapter to ViewPager
m_ViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(m_TabLayout));// performing action of page changing
m_TabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
m_ViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
and tab1 fragment tab code:
public static final String TAG = CDealAppListing.class.getSimpleName();
public static final int m_TRANSACTION_SUCCESSFUL = 0;
public static String m_szMobileNumber;//declaring String mobile number variable
public static String m_szEncryptedPassword;//declaring string password variable
public static String sz_RecordCount;// //declaring String record count variable variable
public static String sz_LastCount;//declaring String lastcount variable
private static ListView m_ListView;// declaring Listview variable..
private static CDealAppListingAdapter m_oAdapter;// declaring DealListingAdapter..
public CDealAppDatastorage item;// declaring DealAppdataStorage
public View mFooter;
public AppCompatButton m_BtnRetry;
/*This Broadcast receiver will listen network state accordingly
which enable or disable create an account button*/
private final BroadcastReceiver m_oInternetChecker = new BroadcastReceiver() {// creating broadcast to receive otp sent by server from Inbox...
#Override
public void onReceive(Context context, Intent intent) {// on receive method to read OTP sent by server
changeButtonState();// check whether edit text is empty or not
}
};
RequestQueue requestQueue;
JsonObjectRequest jsonObjectRequest;
private ArrayList<CDealAppDatastorage> s_oDataset;// declaring Arraylist variable
private int[] m_n_FormImage;//declaring integer array varaible
private View m_Main;//declaring View variable
private int m_n_DefaultRecordCount = 5;// intiallly record count is 5.
private int m_n_DeafalutLastCount = 0;//initally lastcount is 0.
private SwipeRefreshLayout mSwipeRefresh;
private ProgressDialog m_Dialog;
private boolean bBottomOfView;
private LinearLayout m_NoInternetWarning;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
m_Main = inflater.inflate(R.layout.deal_listing, container, false);//intialize mainLayout
Log.i(TAG, "OnCreateView.........");
init();
return m_Main;
}
#Override
public void onResume() {
super.onResume();
Log.i(TAG, "onResume.........");
/*Registered Broadcast receiver*/
IntentFilter m_intentFilter = new IntentFilter();// creating object of Intentfilter class user for defining permission
m_intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");// action to check Internet connection
getActivity().registerReceiver(m_oInternetChecker, m_intentFilter);// register receiver....
getDetails();
}
public void changeButtonState() {
if (NetworkUtil.isConnected(getActivity())) {
m_BtnRetry.setEnabled(true);
m_BtnRetry.setBackgroundColor(Color.rgb(0, 80, 147));// set background color on eabled
} else {
m_BtnRetry.setEnabled(false);
m_BtnRetry.setBackgroundColor(Color.rgb(192, 192, 192));// color of login button
}
}
private void getDetails() {// get details of user from shared preference...
CLoginSessionManagement m_oSessionManagement = new CLoginSessionManagement(getActivity());// crating object of Login Session
HashMap<String, String> user = m_oSessionManagement.getLoginDetails();// get String from Login Session
m_szMobileNumber = user.get(CLoginSessionManagement.s_szKEY_MOBILE).trim();// getting password from saved preferences..........
m_szEncryptedPassword = user.get(CLoginSessionManagement.s_szKEY_PASSWORD).trim();// getting mobile num from shared preferences...
sz_RecordCount = String.valueOf(m_n_DefaultRecordCount);// increment of record count
m_n_DeafalutLastCount = 0;
sz_LastCount = String.valueOf(m_n_DeafalutLastCount);// increment of last count...
s_oDataset = new ArrayList<>();// making object of Arraylist
if (NetworkUtil.isConnected(getActivity())) {
m_NoInternetWarning.setVisibility(View.GONE);
postDealListingDatatoServer();// here sending request in onCreate
} else {
mSwipeRefresh.setVisibility(View.GONE);
m_NoInternetWarning.setVisibility(View.VISIBLE);
m_BtnRetry.setEnabled(false);
m_BtnRetry.setBackgroundColor(Color.rgb(192, 192, 192));// color of login button
}
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy...............");
getActivity().unregisterReceiver(m_oInternetChecker);// unregistaer broadcast receiver.
}
private void init() {// initialize controls
m_NoInternetWarning = (LinearLayout) m_Main.findViewById(R.id.no_internet_warning);
m_BtnRetry = (AppCompatButton) m_Main.findViewById(R.id.btn_retry);
m_BtnRetry.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
retryRequest(v);
}
});
m_ListView = (ListView) m_Main.findViewById(R.id.dealList);// findind Id of Listview
m_ListView.setFadingEdgeLength(0);
m_ListView.setOnScrollListener(this);
/*Swipe to refresh code*/
mSwipeRefresh = (SwipeRefreshLayout) m_Main.findViewById(R.id.swipe);
mSwipeRefresh.setColorSchemeResources(R.color.refresh_progress_1);
mSwipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
/*Here check net connection avialable or not */
if (NetworkUtil.isConnected(getActivity())) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
sz_RecordCount = String.valueOf(m_n_DefaultRecordCount);// increment of record count
m_n_DeafalutLastCount = 0;
sz_LastCount = String.valueOf(m_n_DeafalutLastCount);// increment of last count...
swipeData();
}
}, 3500);
} else {
m_NoInternetWarning.setVisibility(View.VISIBLE);
mSwipeRefresh.setVisibility(View.GONE);
if (mSwipeRefresh.isRefreshing()) {
mSwipeRefresh.setRefreshing(false);
}
}
}
});
m_n_FormImage = new int[]{// defining Images in Integer array
R.drawable.amazon,
R.drawable.whatsapp,
R.drawable.zorpia,
R.drawable.path,
R.drawable.app_me,
R.drawable.evernote,
R.drawable.app_me};
}
public void retryRequest(View v) {
if (NetworkUtil.isConnected(getActivity())) {
m_BtnRetry.setEnabled(true);
m_BtnRetry.setBackgroundColor(Color.rgb(0, 80, 147));// set background color on eabled
sz_RecordCount = String.valueOf(m_n_DefaultRecordCount);// increment of record count
m_n_DeafalutLastCount = 0;
sz_LastCount = String.valueOf(m_n_DeafalutLastCount);// increment of last count...
postDealListingDatatoServer();
} else {
m_BtnRetry.setEnabled(false);
m_BtnRetry.setBackgroundColor(Color.rgb(192, 192, 192));// color of login button
}
}
/*This is new changes in code ....using Volley instead of AsynkTask*/
/*This method send request to server for deallisting*/
// this method send request to server for deal list....
public void postDealListingDatatoServer() {
try {
String json;
// 3. build jsonObject
final JSONObject jsonObject = new JSONObject();// making object of Jsons.
jsonObject.put("agentCode", m_szMobileNumber);// put mobile number
jsonObject.put("pin", m_szEncryptedPassword);// put password
jsonObject.put("recordcount", sz_RecordCount);// put record count
jsonObject.put("lastcountvalue", sz_LastCount);// put last count
System.out.println("Record Count:-" + sz_RecordCount);
System.out.println("LastCount:-" + sz_LastCount);
// 4. convert JSONObject to JSON to String
json = jsonObject.toString();// convert Json object to string
Log.i(TAG, "Server Request:-" + json);
m_Dialog = DialogUtils.showProgressDialog(getActivity().getApplicationContext(), "Loading...");
final String m_DealListingURL = "http://202.131.144.132:8080/json/metallica/getDealListInJSON";
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, m_DealListingURL, jsonObject, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.i(TAG, "Server Response:-" + response);
m_Dialog.dismiss();
try {
int nResultCodeFromServer = Integer.parseInt(response.getString("resultcode"));
if (nResultCodeFromServer == m_TRANSACTION_SUCCESSFUL) {
JSONArray posts = response.optJSONArray("dealList");// get Deal list in array from response
s_oDataset.clear();
for (int i = 0; i < posts.length(); i++) {// loop for counting deals from server
JSONObject post = posts.getJSONObject(i);// counting deal based on index
item = new CDealAppDatastorage();// creating object of DealAppdata storage
item.setM_szHeaderText(post.getString("dealname"));// get deal name from response
item.setM_szsubHeaderText(post.getString("dealcode"));// get dealcode from response
item.setM_szDealValue(post.getString("dealvalue"));// get deal value from response
item.setM_n_Image(m_n_FormImage[i]);//set Image Index wise(Dummy)
s_oDataset.add(item);// add all items in ArrayList
}
if (!s_oDataset.isEmpty()) {// condition if data in arraylist is not empty
m_oAdapter = new CDealAppListingAdapter(getActivity(), s_oDataset);// create adapter object and add arraylist to adapter
m_ListView.setAdapter(m_oAdapter);//adding adapter to recyclerview
m_NoInternetWarning.setVisibility(View.GONE);
mSwipeRefresh.setVisibility(View.VISIBLE);
} else {
m_ListView.removeFooterView(mFooter);// else Load buttonvisibility set to Gone
}
}
if (response.getString("resultdescription").equalsIgnoreCase("Connection Not Available")) {//server based conditions
CSnackBar.getInstance().showSnackBarError(m_Main.findViewById(R.id.mainLayout), "Connection Lost !", getActivity());
} else if (response.getString("resultdescription").equalsIgnoreCase("Deal List Not Found")) {// serevr based conditions .....
CSnackBar.getInstance().showSnackBarError(m_Main.findViewById(R.id.mainLayout), "No more deals available", getActivity());
} else if (response.getString("resultdescription").equalsIgnoreCase("Technical Failure")) {
CSnackBar.getInstance().showSnackBarError(m_Main.findViewById(R.id.mainLayout), "Technical Failure", getActivity());
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Server error:-" + error);
m_Dialog.dismiss();
if (error instanceof TimeoutError) {
CSnackBar.getInstance().showSnackBarError(m_Main.findViewById(R.id.mainLayout), "Connection lost ! Please try again", getActivity());
} else if (error instanceof NetworkError) {
CSnackBar.getInstance().showSnackBarError(m_Main.findViewById(R.id.mainLayout), "No internet connection", getActivity());
mSwipeRefresh.setVisibility(View.GONE);
m_NoInternetWarning.setVisibility(View.VISIBLE);
}
}
});
RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
requestQueue.add(jsonObjectRequest);
} catch (JSONException e) {
e.printStackTrace();
}
}
Step1: Change DialogUtils class:
public static ProgressDialog showProgressDialog(Activity activity, String message) {
ProgressDialog m_Dialog = new ProgressDialog(activity);
m_Dialog.setMessage(message);
m_Dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
m_Dialog.setCancelable(false);
m_Dialog.show();
return m_Dialog;
}
Step2: Change the postDealListingDatatoServer() method.
m_Dialog = DialogUtils.showProgressDialog(getActivity(), "Loading...");
Step3: About broadcast receiver. Please register at the onResume() method and unregister at the onPause() method.
public static ProgressDialog showProgressDialog(Context context, String message) {
ProgressDialog m_Dialog = new ProgressDialog(context);
m_Dialog.setMessage(message);
m_Dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
m_Dialog.setCancelable(false);
if (!((Activity) context).isFinishing()) {
m_Dialog.show();
}
return m_Dialog;
}
To dismiss dialog:
if ((m_Dialog!= null) && m_Dialog.isShowing())
m_Dialog.dismiss();
Check if fragment is visible or not.
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (this.isVisible()) {
// If we are becoming invisible, then...
if (!isVisibleToUser) {
}
} else {
}
}
}

NPE getCount in Adapter when trying to get user albums using FB SDK

I am trying to get the users albums using the FB SDK. I have managed to log-in successfully and am able to retrieve the users profile picture and acquire an access token.
I am following this answer here and am trying to get it to work, but I am running into an issue where I get java.lang.NullPointerException in the adapter class on at com.myapp.myapp.PhotosAdapter.getCount(PhotosAdapter.java:37)
Here's the full set-up as to what I have:
Where am I going wrong? thanks
FBGRID activity:
public class FBGRID extends Activity {
private String URL;
// STORE THE PAGING URL
private String pagingURL;
// FLAG FOR CURRENT PAGE
int current_page = 1;
// BOOLEAN TO CHECK IF NEW FEEDS ARE LOADING
Boolean loadingMore = true;
Boolean stopLoadingData = false;
GridView grid;
ArrayList<getPhotos> arrPhotos;
PhotosAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fbgrid);
grid = (GridView) findViewById(R.id.gridView1);
grid.setOnScrollListener(new OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
int lastInScreen = firstVisibleItem + visibleItemCount;
if ((lastInScreen == totalItemCount) && !(loadingMore)) {
if (stopLoadingData == false) {
// FETCH THE NEXT BATCH OF FEEDS
new loadMorePhotos().execute();
}
}
}
});
new getPhotosData().execute();
}
private class getPhotosData extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... arg0) {
// CHANGE THE LOADING MORE STATUS TO PREVENT DUPLICATE CALLS FOR
// MORE DATA WHILE LOADING A BATCH
loadingMore = true;
Session s = Session.getActiveSession();
// SET THE INITIAL URL TO GET THE FIRST LOT OF ALBUMS
URL = "https://graph.facebook.com/" + "me/albums"
+ "/photos&access_token=" + s.getAccessToken()
+ "?limit=10";
try {
HttpClient hc = new DefaultHttpClient();
HttpGet get = new HttpGet(URL);
HttpResponse rp = hc.execute(get);
if (rp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
String queryAlbums = EntityUtils.toString(rp.getEntity());
JSONObject JOTemp = new JSONObject(queryAlbums);
JSONArray JAPhotos = JOTemp.getJSONArray("data");
// IN MY CODE, I GET THE NEXT PAGE LINK HERE
getPhotos photos;
for (int i = 0; i < JAPhotos.length(); i++) {
JSONObject JOPhotos = JAPhotos.getJSONObject(i);
// Log.e("INDIVIDUAL ALBUMS", JOPhotos.toString());
if (JOPhotos.has("link")) {
photos = new getPhotos();
// GET THE ALBUM ID
if (JOPhotos.has("id")) {
photos.setPhotoID(JOPhotos.getString("id"));
} else {
photos.setPhotoID(null);
}
// GET THE ALBUM NAME
if (JOPhotos.has("name")) {
photos.setPhotoName(JOPhotos.getString("name"));
} else {
photos.setPhotoName(null);
}
// GET THE ALBUM COVER PHOTO
if (JOPhotos.has("picture")) {
photos.setPhotoPicture(JOPhotos
.getString("picture"));
} else {
photos.setPhotoPicture(null);
}
// GET THE PHOTO'S SOURCE
if (JOPhotos.has("source")) {
photos.setPhotoSource(JOPhotos
.getString("source"));
} else {
photos.setPhotoSource(null);
}
arrPhotos.add(photos);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
grid.setAdapter(new PhotosAdapter(FBGRID.this, arrPhotos));
loadingMore = false;
}
}
private class loadMorePhotos extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... arg0) {
// SET LOADING MORE "TRUE"
loadingMore = true;
// INCREMENT CURRENT PAGE
current_page += 1;
// Next page request
URL = pagingURL;
try {
HttpClient hc = new DefaultHttpClient();
HttpGet get = new HttpGet(URL);
HttpResponse rp = hc.execute(get);
if (rp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
String queryAlbums = EntityUtils.toString(rp.getEntity());
// Log.e("PAGED RESULT", queryAlbums);
JSONObject JOTemp = new JSONObject(queryAlbums);
JSONArray JAPhotos = JOTemp.getJSONArray("data");
// IN MY CODE, I GET THE NEXT PAGE LINK HERE
getPhotos photos;
for (int i = 0; i < JAPhotos.length(); i++) {
JSONObject JOPhotos = JAPhotos.getJSONObject(i);
// Log.e("INDIVIDUAL ALBUMS", JOPhotos.toString());
if (JOPhotos.has("link")) {
photos = new getPhotos();
// GET THE ALBUM ID
if (JOPhotos.has("id")) {
photos.setPhotoID(JOPhotos.getString("id"));
} else {
photos.setPhotoID(null);
}
// GET THE ALBUM NAME
if (JOPhotos.has("name")) {
photos.setPhotoName(JOPhotos.getString("name"));
} else {
photos.setPhotoName(null);
}
// GET THE ALBUM COVER PHOTO
if (JOPhotos.has("picture")) {
photos.setPhotoPicture(JOPhotos
.getString("picture"));
} else {
photos.setPhotoPicture(null);
}
// GET THE ALBUM'S PHOTO COUNT
if (JOPhotos.has("source")) {
photos.setPhotoSource(JOPhotos
.getString("source"));
} else {
photos.setPhotoSource(null);
}
arrPhotos.add(photos);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// get listview current position - used to maintain scroll position
int currentPosition = grid.getFirstVisiblePosition();
// APPEND NEW DATA TO THE ARRAYLIST AND SET THE ADAPTER TO THE
// LISTVIEW
adapter = new PhotosAdapter(FBGRID.this, arrPhotos);
grid.setAdapter(adapter);
// Setting new scroll position
grid.setSelection(currentPosition + 1);
// SET LOADINGMORE "FALSE" AFTER ADDING NEW FEEDS TO THE EXISTING
// LIST
loadingMore = false;
}
}
public class getPhotos {
String PhotoID;
String PhotoName;
String PhotoPicture;
String PhotoSource;
// SET THE PHOTO ID
public void setPhotoID(String PhotoID) {
this.PhotoID = PhotoID;
}
// GET THE PHOTO ID
public String getPhotoID() {
return PhotoID;
}
// SET THE PHOTO NAME
public void setPhotoName(String PhotoName) {
this.PhotoName = PhotoName;
}
// GET THE PHOTO NAME
public String getPhotoName() {
return PhotoName;
}
// SET THE PHOTO PICTURE
public void setPhotoPicture(String PhotoPicture) {
this.PhotoPicture = PhotoPicture;
}
// GET THE PHOTO PICTURE
public String getPhotoPicture() {
return PhotoPicture;
}
// SET THE PHOTO SOURCE
public void setPhotoSource(String PhotoSource) {
this.PhotoSource = PhotoSource;
}
// GET THE PHOTO SOURCE
public String getPhotoSource() {
return PhotoSource;
}
}
}
and for the Adapter class(it uses an image loading library):
final class PhotosAdapter extends BaseAdapter {
private Activity activity;
ArrayList<getPhotos> arrayPhotos;
private static LayoutInflater inflater = null;
ImageLoader imageLoader;
public PhotosAdapter(Activity a, ArrayList<getPhotos> arrPhotos) {
activity = a;
arrayPhotos = arrPhotos;
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader = new ImageLoader(activity.getApplicationContext());
}
public int getCount() {
return arrayPhotos.size();
}
public Object getItem(int position) {
return arrayPhotos.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View vi = convertView;
if (convertView == null) {
vi = inflater.inflate(R.layout.photos_item, null);
holder = new ViewHolder();
holder.imgPhoto = (ImageView) vi.findViewById(R.id.grid_item_image);
vi.setTag(holder);
} else {
holder = (ViewHolder) vi.getTag();
}
if (arrayPhotos.get(position).getPhotoPicture() != null) {
imageLoader.DisplayImage(arrayPhotos.get(position)
.getPhotoPicture(), holder.imgPhoto);
}
return vi;
}
static class ViewHolder {
ImageView imgPhoto;
}
}
Here's logcat:
FATAL EXCEPTION: main
java.lang.NullPointerException
at com.myapp.myapp.PhotosAdapter.getCount(PhotosAdapter.java:37)
at android.widget.GridView.setAdapter(GridView.java:186)
at com.myapp.myapp.FBGRID$getPhotosData.onPostExecute(FBGRID.java:173)
at com.myapp.myapp.FBGRID$getPhotosData.onPostExecute(FBGRID.java:1)
at android.os.AsyncTask.finish(AsyncTask.java:631)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:5225)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:741)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
at dalvik.system.NativeStart.main(Native Method)

Categories

Resources