I am making a news feed where I retrieve Facebook posts from a specific Facebook page. I retrieve those posts with help of the Facebook Graph API. I have a FeedItem which has an ID (int). The ID is also used to check which item is at the current position (Recyclerview).
The problem is that Facebook gives the posts a String ID. I have no idea how I can possibly convert this so that it will work with my application.
My Adapter:
public class FeedListAdapter extends RecyclerView.Adapter<FeedListAdapter.ViewHolder> {
private ImageLoader imageLoader = AppController.getInstance().getImageLoader();
private List<FeedItem> mFeedItems;
private Context mContext;
public FeedListAdapter(List<FeedItem> pFeedItems, Context pContext) {
this.mFeedItems = pFeedItems;
this.mContext = pContext;
}
/* Create methods for further adapter use.*/
#Override
public ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
View feedView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.feed_item, parent, false);
return new ViewHolder(feedView);
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.populateRow(getFeedItem(position));
}
#Override
public long getItemId(int position) {
return mFeedItems.get(position).getId();
}
#Override
public int getItemCount() {
return mFeedItems.size();
}
private FeedItem getFeedItem(int position) {
return mFeedItems.get(position);
}
class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener {
private ImageView mProfilePic;
private TextView mName;
private TextView mTimestamp;
private TextView mTxtStatusMsg;
private FeedImageView mFeedImage;
//initialize the variables
ViewHolder(View view) {
super(view);
mProfilePic = (ImageView) view.findViewById(R.id.feedProfilePic);
mName = (TextView) view.findViewById(R.id.feedName);
mTimestamp = (TextView) view.findViewById(R.id.feedTimestamp);
mTxtStatusMsg = (TextView) view.findViewById(R.id.feedStatusMessage);
mFeedImage = (FeedImageView) view.findViewById(R.id.feedImage);
view.setOnClickListener(this);
}
#Override
public void onClick(View view) {
}
private void populateRow(FeedItem pFeedItem) {
getProfilePic(pFeedItem);
mName.setText(pFeedItem.getName());
mTimestamp.setText(pFeedItem.getTimeStamp());
mTxtStatusMsg.setText(pFeedItem.getStatus());
getStatusImg(pFeedItem);
}
private void getProfilePic(FeedItem pFeedItem) {
imageLoader.get(pFeedItem.getProfilePic(), new ImageListener() {
#Override
public void onResponse(ImageContainer response, boolean arg1) {
if (response.getBitmap() != null) {
// load image into imageview
mProfilePic.setImageBitmap(response.getBitmap());
}
}
#Override
public void onErrorResponse(final VolleyError pVolleyError) {
}
});
}
private void getStatusImg(FeedItem pFeedItem) {
if (pFeedItem.getImage() != null) {
mFeedImage.setImageUrl(pFeedItem.getImage(), imageLoader);
mFeedImage.setVisibility(View.VISIBLE);
mFeedImage
.setResponseObserver(new FeedImageView.ResponseObserver() {
#Override
public void onError() {
}
#Override
public void onSuccess() {
}
});
} else {
mFeedImage.setVisibility(View.GONE);
}
}
}
My FeedFragment:
public class FeedFragment extends android.support.v4.app.Fragment {
private static final String TAG = FeedFragment.class.getSimpleName();
private FeedListAdapter mListAdapter;
private List<FeedItem> mFeedItems;
private RecyclerView mRecyclerView;
private String FACEBOOKURL = "**URL OF MY FB-POSTDATA**";
// newInstance constructor for creating fragment with arguments
public static FeedFragment newInstance() {
FeedFragment fragment = new FeedFragment();
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout resource file
View view = getActivity().getLayoutInflater().inflate(R.layout.fragment_feed, container, false);
initRecyclerView(view);
initCache();
return view;
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onResume() {
super.onResume();
}
private void initRecyclerView(View pView) {
mRecyclerView = (RecyclerView) pView.findViewById(R.id.fragment_feed_recyclerview);
LayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setHasFixedSize(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mRecyclerView.setNestedScrollingEnabled(true);
}
mFeedItems = new ArrayList<>();
mListAdapter = new FeedListAdapter(mFeedItems, getActivity());
mRecyclerView.setAdapter(mListAdapter);
}
private void initCache() {
// We first check for cached request
Cache cache = AppController.getInstance().getRequestQueue().getCache();
Entry entry = cache.get(FACEBOOKURL);
if (entry != null) {
// fetch the data from cache
try {
String data = new String(entry.data, "UTF-8");
try {
parseJsonFeed(new JSONObject(data));
} catch (JSONException e) {
e.printStackTrace();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else {
// making fresh volley request and getting json
JsonObjectRequest jsonReq = new JsonObjectRequest(Method.GET,
FACEBOOKURL, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
VolleyLog.d(TAG, "Response: " + response.toString());
if (response != null) {
parseJsonFeed(response);
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
}
});
// Adding request to volley request queue
AppController.getInstance().addToRequestQueue(jsonReq);
}
}
private void parseJsonFeed(JSONObject response) {
try {
JSONArray feedArray = response.getJSONArray("data");
for (int i = 0; i < feedArray.length(); i++) {
JSONObject feedObj = (JSONObject) feedArray.get(i);
FeedItem item = new FeedItem();
item.setId(Integer.parseInt(feedObj.getString("id")));
item.setName("name of page");
// Image might be null sometimes
String image = feedObj.isNull("full_picture") ? null : feedObj
.getString("full_picture");
item.setImage(image);
// Status message might be null sometimes
String status = feedObj.isNull("message") ? null : feedObj
.getString("message");
item.setStatus(status);
item.setProfilePic("**profile picture url**");
item.setTimeStamp(feedObj.getString("created_time"));
mFeedItems.add(item);
}
// notify data changes to list adapter
mListAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
} }
As I said; I have no idea how to handle this and I figured someone here would maybe have an idea on how to convert this, so that I can use the String that the graph api gives me, and use it as an integer.
If the id is all numeric, you should be able to do this: int id = Integer.valueOf(facebookId)
If you have an undescore you can try this:
public int getIdFromString(String postId) {
String finalId;
while (postId.indexOf("_") > 0) {
finalId = postId.substring(0, postId.indexOf("_"));
postId = finalId.concat(postId.substring(postId.indexOf("_") + 1));
}
return Integer.valueOf(postId);
}
If the value is numeric and you want an integer object, do
Integer id = Integer.valueOf(facebookId);
If you want the primitive type int, then do
int id = Integer.parseInt(facebookId);
or
int id = Integer.valueOf(facebookId);
Related
I write this code but not show me anything and in logcat have no error
and I have three classes for this code Adapter, recyclertouchlistener and fragments code...
my code in below
this code for fragment :
public class VerticalRecyclerFragment extends Fragment {
RecyclerView rcVertical;
static ArrayList<Products> productsArrayList = new ArrayList<>();
public VerticalRecyclerFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_vertical_recycler,
container, false);
showProduct();
rcVertical = view.findViewById(R.id.rcVertical);
rcVertical.addOnItemTouchListener(new RecyclerTouchListener(getContext(), rcVertical,
new RecyclerTouchListener.ClickListener() {
#Override
public void onClick(View view, int position) {
ProductActivity.products = productsArrayList.get(position);
startActivity(new Intent(getActivity(), ProductActivity.class));
}
#Override
public void onLongClick(View view, int position) {
}
}));
Adapter adapter = new Adapter(productsArrayList, getContext());
rcVertical.setLayoutManager(new LinearLayoutManager(getActivity()));
rcVertical.setItemAnimator(new DefaultItemAnimator());
rcVertical.setAdapter(adapter);
return view;
}
public void showProduct() {
final ProgressDialog loader = ProgressDialog.show(getActivity(),
"Get products...", "please wait",
false, false);
StringRequest request = new StringRequest(Request.Method.POST,
Config.getProductsWebApi,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
loader.dismiss();
productsArrayList.clear();
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray jsonArray = jsonObject.getJSONArray("response");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject object = jsonArray.getJSONObject(i);
String id = object.getString("id");
String name = object.getString("name");
String description = object.getString("description");
String price = object.getString("price");
String photo = object.getString("photo");
Products p = new Products(id, name, description, price, photo);
productsArrayList.add(p);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
loader.dismiss();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
requestQueue.add(request);
}}
and i write this code for Adapter in a single class :
public class Adapter extends RecyclerView.Adapter<Adapter.MyHolder> {
ArrayList<Products> ProductsList;
Context context;
public Adapter(ArrayList<Products> productsList, Context context) {
ProductsList = productsList;
this.context = context;
}
#Override
public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.row_layout, parent, false);
return new MyHolder(v);
}
#Override
public void onBindViewHolder(MyHolder holder, final int position) {
Products products = ProductsList.get(position);
holder.txtName.setText(products.getName());
holder.txtPrice.setText("$ " + products.getPrice());
Picasso.get().load(Config.ipValue + "/images/" + products.getPhoto()).into(holder.imgV);
holder.imgV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
v.startAnimation(AnimationUtils.loadAnimation(context, android
.R.anim.slide_in_left));
}
});
}
#Override
public int getItemCount() {
return ProductsList.size();
}
class MyHolder extends RecyclerView.ViewHolder {
TextView txtName;
TextView txtPrice;
ImageView imgV;
public MyHolder(View itemView) {
super(itemView);
txtName = itemView.findViewById(R.id.rowTxtProductName);
txtPrice = itemView.findViewById(R.id.rowTxtPrice);
imgV = itemView.findViewById(R.id.rowImgProduct);
}
}}
RecyclerTouchListener :
public class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {
private GestureDetector gestureDetector;
private ClickListener clickListener;
public RecyclerTouchListener(Context context, final RecyclerView recyclerView,
final ClickListener clickListener) {
this.clickListener = clickListener;
gestureDetector = new GestureDetector(context,
new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
#Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null) {
clickListener.onLongClick(child, recyclerView.getChildPosition(child));
}
}
});
}
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
clickListener.onClick(child,rv.getChildPosition(child));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
public interface ClickListener {
void onClick(View view, int position);
void onLongClick(View view, int position);
}}
Please if you know whats the problem help me to debug it...
thank you
You need to notifyDataSetChanged() when you get the response.
Make the adapter as a class field
public class VerticalRecyclerFragment extends Fragment {
RecyclerView rcVertical;
static ArrayList<Products> productsArrayList = new ArrayList<>();
Adapter adapter; // <<< Change here
change the initialization (and every call of the adapter to the class field)
adapter = new Adapter(productsArrayList, getContext()); // <<< Change here
rcVertical.setLayoutManager(new LinearLayoutManager(getActivity()));
rcVertical.setItemAnimator(new DefaultItemAnimator());
rcVertical.setAdapter(adapter);
And finally call notifyDataSetChanged() when you get the response
public void showProduct() {
final ProgressDialog loader = ProgressDialog.show(getActivity(),
"Get products...", "please wait",
false, false);
StringRequest request = new StringRequest(Request.Method.POST,
Config.getProductsWebApi,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
loader.dismiss();
productsArrayList.clear();
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray jsonArray = jsonObject.getJSONArray("response");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject object = jsonArray.getJSONObject(i);
String id = object.getString("id");
String name = object.getString("name");
String description = object.getString("description");
String price = object.getString("price");
String photo = object.getString("photo");
Products p = new Products(id, name, description, price, photo);
productsArrayList.add(p);
}
adapter.notifyDataSetChanged(); // <<< Change here
} catch (JSONException e) {
e.printStackTrace();
}
}
}...
...
}
UPDATE:
add attach the adapter to the RecyclerView when you receive the data
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject object = jsonArray.getJSONObject(i);
String id = object.getString("id");
String name = object.getString("name");
String description = object.getString("description");
String price = object.getString("price");
String photo = object.getString("photo");
Products p = new Products(id, name, description, price, photo);
productsArrayList.add(p);
}
Adapter adapter = new Adapter(productsArrayList, getContext()); // <<< Change here
rcVertical.setAdapter(adapter); // <<< Change here
I am fetching data from a server in a recycler view.In a layout file I have an EditText field on top and below it I have a recycler view.
I want to filter data based on what I have written in EditText field.
My problem is as I start typing in EditText field it shows no data in recycler and as I removes everything in EditText field it shows everything.
Why it is happening even if I have data present in recycler view with the same name I have entered in EditText field.
This is my code below:
Home.java
public class Home extends Fragment {
String myValue;
RecyclerView recycle;
ArrayList<LoadHomeBooks> list;
HomeBookAdapter adapter;
EditText search;
private static final String URL = "https://www.example.com";
public Home() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_home, container, false);
recycle = view.findViewById(R.id.recycle);
refresh = view.findViewById(R.id.refresh);
search = view.findViewById(R.id.search);
list = new ArrayList<>();
recycle.setHasFixedSize(true);
recycle.setLayoutManager(new LinearLayoutManager(getActivity()));
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(22, TimeUnit.SECONDS)
.readTimeout(22, TimeUnit.SECONDS)
.writeTimeout(22, TimeUnit.SECONDS)
.build();
RequestBody formBody = new FormBody.Builder().add("city", myValue).build();
Request request = new Request.Builder().url(URL).post(formBody).build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onResponse(Call call, final Response response) throws IOException {
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
try {
JSONArray jsonArray = new JSONArray(response.body().string());
for (int i = jsonArray.length() - 1; i > -1; i--) {
JSONObject object = jsonArray.getJSONObject(i);
String str1 = object.getString("Book_name");
LoadHomeBooks model = new LoadHomeBooks(str1);
list.add(model);
}
adapter = new HomeBookAdapter(list, getActivity());
recycle.setAdapter(adapter);
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
#Override
public void onFailure(Call call, final IOException e) {
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
TastyToast.makeText(getActivity(), e.getMessage(), TastyToast.LENGTH_LONG, TastyToast.ERROR).show();
}
});
}
}
});
search.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
ArrayList<LoadHomeBooks> filterBooks = new ArrayList<>();
for(LoadHomeBooks books: list){
String name = books.getbName().toLowerCase();
if(name.contains(s)){
filterBooks.add(books);
}
adapter.setFilter(filterBooks);
}
}
});
return view;
}
}
HomeBookAdapter.java
public class HomeBookAdapter extends RecyclerView.Adapter<HomeBookAdapter.ViewHolder> {
ArrayList<LoadHomeBooks> list;
Context context;
public HomeBookAdapter(ArrayList<LoadHomeBooks> list,Context context){
this.list = list;
this.context = context;
}
#NonNull
#Override
public HomeBookAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.home_book_layout,viewGroup,false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull HomeBookAdapter.ViewHolder viewHolder, int i) {
LoadHomeBooks model = list.get(i);
viewHolder.homeBookName.setText(model.getbName());
}
#Override
public int getItemCount() {
return list.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
TextView homeBookName;
public ViewHolder(#NonNull View itemView) {
super(itemView);
homeBookName = itemView.findViewById(R.id.homeBookName);
}
}
public void setFilter(ArrayList<LoadHomeBooks> filterBooks){
list = new ArrayList<>();
list.addAll(filterBooks);
notifyDataSetChanged();
}
}
LoadHomeBooks.java
public class LoadHomeBooks {
String bName;
public LoadHomeBooks(){
}
public LoadHomeBooks(String bName){
this.bName = bName;
}
public String getbName() {
return bName;
}
public void setbName(String bName) {
this.bName = bName;
}
}
Someone please let me know what I am doing wrong. Any help would be appreciated.
THANKS
Move this code outside the for Loop
adapter.setFilter(filterBooks);
Because adapter is calling set Filter after each iteration.
Also I would request you to move network request to Activity instead of Fragment using interface.
for(LoadHomeBooks books: list){
String name = books.getbName().toLowerCase();
if(name.contains(s)){
filterBooks.add(books);
}
adapter.setFilter(filterBooks); //Place this line outside forloop
}
My recyclerview is not updating correctly after the back button is
pressed.
The recyclerview works fine before the back button is pressed
The data is properly updated (seen in the log) but the recyclerview does not reflect the change
The purpose of the handler is to poll the database for a notification (working fine)
The notification toast is displayed everytime
I am not receiving any errors
If I can provide any other information to help do not hesitate to ask.
Main:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat_room);
recView = (RecyclerView) findViewById(R.id.recyclerViewMessages);
linearLayoutManager = new LinearLayoutManager(this) {};
linearLayoutManager.setReverseLayout(true);
recView.setLayoutManager(linearLayoutManager);
listData = (ArrayList) MessagingData.getMessageListData();
adapter = new RecyclerViewAdapterMessaging(listData, this);
recView.setAdapter(adapter);
adapter.setItemClickCallback(this);
final Handler h = new Handler();
final int delay = 2000; //milliseconds
h.postDelayed(new Runnable(){
public void run(){
Notify_Message_Async notify_message_async = new Notify_Message_Async(ctx);
notify_message_async.execute(NOTIFICATION, message_id);
System.out.println(global.getNotification());
if(global.getNotification()==1){
Toast.makeText(ctx, "Notified",
Toast.LENGTH_LONG).show();
try {
refresh_receive();
} catch (ExecutionException e) {
Toast.makeText(ctx, "catch",
Toast.LENGTH_LONG).show();
e.printStackTrace();
} catch (InterruptedException e) {
Toast.makeText(ctx, "catch",
Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
h.postDelayed(this, delay);
}
}, delay);
}
public void refresh_receive() throws ExecutionException, InterruptedException {
String method = "receive_message";
Receive_Live_Message_Async receive_live_message_async = new Receive_Live_Message_Async(this);
receive_live_message_async.execute(method, message_id).get();// Setup the message
adapter.setListData((ArrayList)MessagingData.getMessageListData());
adapter.notifyDataSetChanged();
global.setNotification(0);//reset notification
}
Adapter:
public class RecyclerViewAdapterMessaging extends RecyclerView.Adapter<RecyclerViewAdapterMessaging.Holder> {
private View v;
private List<List_Item_Messaging> listData;
private LayoutInflater inflater;
Global global = new Global();
private ItemClickCallback itemClickCallback;
Context context;
public interface ItemClickCallback {
void onItemClick(View v, int p);
void onSecondaryIconClick(int p);
}
public void setItemClickCallback(final ItemClickCallback itemClickCallback) {
this.itemClickCallback = itemClickCallback;
}
public RecyclerViewAdapterMessaging(List<List_Item_Messaging> listData, Context c) {
inflater = LayoutInflater.from(c);
context = c;
this.listData = listData;
}
#Override
public int getItemViewType(int position) {//0 for self... /1 for Other
List_Item_Messaging item = listData.get(position);
//ENSURE GLOBAL USERNAME NOT NULL
String other_username = item.getMessage_username();
if (other_username == null) {
((Activity) context).finish();
}
if (item.getMessage_username().trim().equals(global.getUserName())) {
System.out.println("The usernames are the same");
return 0;
} else {
System.out.println("The usernames are the NOT same");
return 1;
}
}
#Override
public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case 0:
View view = inflater.inflate(R.layout.chat_thread, parent, false);// Self
v = view;
break;
case 1:
View view2 = inflater.inflate(R.layout.chat_thread_other, parent, false);// Not self
int width2 = global.getScreenWidth();
v = view2;
break;
}
return new Holder(v);
}
#Override
public void onBindViewHolder(Holder holder, int position) {
List_Item_Messaging item = listData.get(position);
holder.conversation.setText(item.getMessage_conversation());
}
public void setListData(ArrayList<List_Item_Messaging> exerciseList) {
this.listData.clear();
this.listData.addAll(exerciseList);
}
#Override
public int getItemCount() {
return listData.size();
}
class Holder extends RecyclerView.ViewHolder implements View.OnClickListener {
ImageView thumbnail;
//ImageView secondaryIcon;
TextView conversation;
View message_container;
public Holder(View itemView) {
super(itemView);
conversation = (TextView) itemView.findViewById(R.id.conversation_textview);
message_container = itemView.findViewById(R.id.message_container);
message_container.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.message_container) {
itemClickCallback.onItemClick(v, getAdapterPosition());
} else {
itemClickCallback.onSecondaryIconClick(getAdapterPosition());
}
}
}
public void clearItems() {
listData.clear();
this.notifyDataSetChanged();
}
}
I have referenced the following to no solution:
notifyDataSetChanged not working on RecyclerView
smoothScrollToPosition after notifyDataSetChanged not working in android
adapter.notifyDataSetChange() not working after called from onResume()
change a little in your code
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat_room);
recView = (RecyclerView) findViewById(R.id.recyclerViewMessages);
linearLayoutManager = new LinearLayoutManager(this) {};
linearLayoutManager.setReverseLayout(true);
recView.setLayoutManager(linearLayoutManager);
// change here
if (listData != null)
listData.clear();
else listData = new <> ArrayList();
listData.addAdd((ArrayList)MessagingData.getMessageListData());
adapter = new RecyclerViewAdapterMessaging(listData, this);
recView.setAdapter(adapter);
adapter.setItemClickCallback(this);
final Handler h = new Handler();
final int delay = 2000; //milliseconds
then make a small change here
public void refresh_receive() throws ExecutionException, InterruptedException {
String method = "receive_message";
Receive_Live_Message_Async receive_live_message_async = new Receive_Live_Message_Async(this);
receive_live_message_async.execute(method, message_id).get();// Setup the message
// changing here
dataList.clear();
dataList.addAdd((ArrayList)MessagingData.getMessageListData())
adapter.setListData(dataList);
adapter.notifyDataSetChanged();
global.setNotification(0);//reset notification
}
another problem in your code, you are using receive_live_message_async AsyncTask
put your update code in onPostExecute
public class receive_live_message_async extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(Object o) {
// call your refresh_receive(); here
super.onPostExecute(o);
}
}
similarly when you are call receive_live_message_async.execute(); update your recyclerView in onPostExecute
#Override
protected void onPostExecute(Object o) {
dataList.clear();
dataList.addAll((ArrayList)MessagingData.getMessageListData());
adapter.notifyDataSetChanged();
super.onPostExecute(o);
}
Main Code
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.movie);
lv =(ListView)findViewById(R.id.lstMovieData);
moviename.clear();
// tv = (TextView) findViewById(R.id.tv);
Bundle b = getIntent().getExtras();
try {
Title = b.getString("MOVIE");
t = replace(Title);
} catch (Exception e) {
}
String API = "https://api.cinemalytics.com/v1/movie/title/?value=" + t + "&auth_token=<token>";
Toast.makeText(getApplicationContext(), Title, Toast.LENGTH_LONG).show();
OkHttpClient Client = new OkHttpClient();
Request request = new Request.Builder()
.url(API).build();
Call call = Client.newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
}
#Override
public void onResponse(final Response response) throws IOException {
try {
String json = response.body().string();
Log.v(TAG, json);
if (response.isSuccessful()) {
getDATA(json);
runOnUiThread(new Runnable() {
#Override
public void run() {
mAdapter = new MovieAdapter(getApplicationContext(),moviename);
lv.setAdapter(mAdapter);
}
});
} else {
}
} catch (Exception e) {
}
}
});
}
public String replace(String str) {
return str.replaceAll(" ", "%20");
}
private void getDATA(String json) throws JSONException {
try {
moviename = new ArrayList<>();
Currentmovie c = new Currentmovie();
String story = "About The Story";
JSONArray values = new JSONArray(json);
for(int i = 0; i < values.length(); i++) {
JSONObject jsonObject = values.getJSONObject(i);
String movieTitle = jsonObject.getString("Title");
String disc = jsonObject.getString("Description");
Log.e(TAG,"GIRISH"+movieTitle);
c= new Currentmovie();
c.setTitle("Movie Name::"+movieTitle);
c.setDesc(story+"::\n"+disc);
if(jsonObject.getString("Description")==null)
{
c.setDesc(story+"::Not Available");
}
moviename.add(c);
}
}
catch (Exception e)
{
System.out.println("Error in Result as " + e.toString());
}
}
2.MovieAdapter.java
public class MovieAdapter extends BaseAdapter {
Context context;
private List<Currentmovie> movieData;
private static LayoutInflater inflater = null;
public MovieAdapter( Context context,List<Currentmovie> movieData)
{
this.context = context;
this.movieData = movieData;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return movieData.size();
}
#Override
public Object getItem(int position) {
return movieData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public static class ViewHolder{
public TextView movieTitle,movieDesc;
public ImageView movieImage;
}
public View getView(int position, View convertView, ViewGroup parent)
{
View vi = convertView;
ViewHolder holder;
if(convertView==null){
vi = inflater.inflate(R.layout.row, null);
holder = new ViewHolder();
holder.movieTitle = (TextView) vi.findViewById(R.id.tv);
holder.movieDesc=(TextView)vi.findViewById(R.id.tv1);
vi.setTag( holder );
}
else
holder=(ViewHolder)vi.getTag();
holder.movieTitle.setText(movieData.get(position).getTitle());
holder.movieDesc.setText(movieData.get(position).getDesc());
return vi;
}
}
//i can successfully show all data except image
//image link comes with "posterpath" key
//tell me how to load image in viewholder of MovieAdapter
//currentmovie is just a getter and setter class
3.Currentmovie.java
public class Currentmovie {
private String mTitle;
private String Description;
public String getDesc() {
return Description;
}
public void setDesc(String desc) {
Description = desc;
}
public String getTitle() {
return mTitle;
}
public void setTitle(String title) {
mTitle = title;
}
}
I am using this library and loading images by
first creating the Display options object by
DisplayImageOptions builder = new DisplayImageOptions.Builder()
.cacheOnDisk(true)
.showImageOnLoading(R.drawable.empty_photo)
.showImageForEmptyUri(R.drawable.empty_photo)
.build();
Then initialze the image loader by
ImageLoader imageLoader = ImageLoader.getInstance();
and load images by
imageLoader.displayImage(url, imageView, builder);
Hope this helps..
also add this to you gradle
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
Refer this first
EDIT: Add this to onCreate() of activity
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this)
...
.build();
ImageLoader.getInstance().init(config);
or this
ImageLoader.getInstance().init(ImageLoaderConfiguration.createDefault(Activity.this));
Add getter and setter methods for your Image like
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imgUrl) {
imageUrl= imgUrl;
}
Add this code in your adapter class after adding Picasso library to your project:
String imageUrl = movieData.get(position).getImageUrl();
Picasso.with(getContext())
.load(imageUrl)
.into(holder.movieImage, new com.squareup.picasso.Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
}
});
I have a list view containing few fields coming from back end. One feed is 'number of likes'.
When I click on any list row it opens one activity for that row, there like button in that activity. When user presses like it get appended on server.
Now the problem is it should show incremented value in the list view when user go back to list view activity. How to do that?
NOTE: Like counter is incremented if I close the app and start it again.
I tried to call on Create method again from on Resume method but it produces duplicate copy of rows every time list view activity is remusmed.
Here is my list activity code.
public class MainActivity extends Activity {
// Session Manager Class
SessionManager session;
// Log tag
private static final String TAG = MainActivity.class.getSimpleName();
// Movies json url
private static final String url = "MY_URL";
private ProgressDialog pDialog;
private List<Movie> movieList = new ArrayList<Movie>();
private ListView listView;
private CustomListAdapter adapter;
{
// Creating volley request obj
JsonArrayRequest movieReq = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
hidePDialog();
// Parsing json
for (int i = 0; i < response.length(); i++) {
try {
JSONObject obj = response.getJSONObject(i);
Movie movie = new Movie();
movie.setThumbnailUrl(obj.getString("image"));
movie.setTitle(obj.getString("title"));
movie.setDate(obj.getString("date"));
movie.setVideo(obj.getString("video"));
movie.setLikes(obj.getInt("likes"));
movie.setId(obj.getInt("id"));
// adding movie to movies array
movieList.add(movie);
} catch (JSONException e) {
e.printStackTrace();
}
}
// notifying list adapter about data changes
// so that it renders the list view with updated data
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
hidePDialog();
}
});
// Adding request to request queue
AppController.getInstance().addToRequestQueue(movieReq);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//creating unique ID
final String deviceId = Settings.Secure.getString(this.getContentResolver(),
Settings.Secure.ANDROID_ID);
Toast.makeText(this, deviceId, Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), "User Login Status: " + session.isLoggedIn(), Toast.LENGTH_LONG).show();
/**
* Call this function whenever you want to check user login
* This will redirect user to LoginActivity is he is not
* logged in
* */
session.checkLogin();
listView = (ListView) findViewById(R.id.list);
adapter = new CustomListAdapter(this, movieList);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// getting values from selected ListItem
// ImageView thumbNail = (ImageView)view.findViewById(R.id.thumbnail);
String title = ((TextView) view.findViewById(R.id.title)).getText().toString();
String likes = ((TextView)view.findViewById(R.id.likes)).getText().toString();
String date = ((TextView)view.findViewById(R.id.date)).getText().toString();
String video = ((TextView) view.findViewById(R.id.video)).getText().toString();
String idd = ((TextView) view.findViewById(R.id.idd)).getText().toString();
// Starting single contact activity
Intent in = new Intent(getApplicationContext(), MovieDetailActivity.class);
// in.putExtra("THUMB", thumbNail.toString());
in.putExtra("TITLE", title);
in.putExtra("LIKES", likes);
in.putExtra("DATE", date);
in.putExtra("VIDEO", video);
in.putExtra("IDD", idd);
in.putExtra("UNIQUEID",deviceId);
//in.putExtra(TAG_URL,"url");
// in.putExtra(TAG_PHONE_MOBILE, description);
startActivity(in);
}
}
);
// Creating volley request obj
enter code here
JsonArrayRequest movieReq = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
hidePDialog();
// Parsing json
for (int i = 0; i < response.length(); i++) {
try {
JSONObject obj = response.getJSONObject(i);
Movie movie = new Movie();
movie.setThumbnailUrl(obj.getString("image"));
movie.setTitle(obj.getString("title"));
movie.setDate(obj.getString("date"));
movie.setVideo(obj.getString("video"));
movie.setLikes(obj.getInt("likes"));
movie.setId(obj.getInt("id"));
// adding movie to movies array
movieList.add(movie);
} catch (JSONException e) {
e.printStackTrace();
}
}
// notifying list adapter about data changes
// so that it renders the list view with updated data
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
hidePDialog();
}
});
// Adding request to request queue
AppController.getInstance().addToRequestQueue(movieReq);
}
#Override
protected void onResume() {
super.onResume();
}
#Override
public void onDestroy() {
super.onDestroy();
hidePDialog();
}
private void hidePDialog() {
if (pDialog != null) {
pDialog.dismiss();
pDialog = null;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
public class CustomListAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<Movie> movieItems;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
public CustomListAdapter(Activity activity, List<Movie> movieItems) {
this.activity = activity;
this.movieItems = movieItems;
}
#Override
public int getCount() {
return movieItems.size();
}
#Override
public Object getItem(int location) {
return movieItems.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.list_row, null);
if (imageLoader == null)
imageLoader = AppController.getInstance().getImageLoader();
NetworkImageView thumbNail = (NetworkImageView) convertView
.findViewById(R.id.thumbnail);
TextView title = (TextView) convertView.findViewById(R.id.title);
TextView likes = (TextView) convertView.findViewById(R.id.likes);
TextView date = (TextView) convertView.findViewById(R.id.date);
TextView video = (TextView) convertView.findViewById(R.id.video);
TextView id = (TextView) convertView.findViewById(R.id.idd);
//TextView year = (TextView) convertView.findViewById(R.id.releaseYear);
// getting movie data for the row
Movie m = movieItems.get(position);
// thumbnail image
thumbNail.setImageUrl(m.getThumbnailUrl(), imageLoader);
// title
title.setText(m.getTitle());
// rating
date.setText(m.getDate());
video.setText(m.getVideo());
likes.setText(String.valueOf(m.getLikes()));
id.setText(String.valueOf(m.getId()));
return convertView;
// Listview on item click listener
}
#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
}
Requested implementation using a SortedList and RecyclerView:
Here is the example I used to build mine.
This is my slightly more complex code that includes sorting via a SearchView in the toolbar. You can use the example in the above link if you want the example without the sorting. The control logic is in my Presenter class that manages this adapter and the Fragment:
public class AdapterInstitutionList extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
// lists to control all items and items visible after sorting
private SortedList<MInstitutionInfo> visibleList;
private ArrayList<MInstitutionInfo> allItems;
// my fragment and the presenter
private FInstitutionSelection fInstitutionSelection;
private PInstitutionList presenter;
public AdapterInstitutionList(PInstitutionList pInstitutionSelection, FInstitutionSelection fInstitutionSelection) {
// get ref to fragment, presenter, and create new callback for sortedlist
this.fInstitutionSelection = fInstitutionSelection;
presenter = pInstitutionSelection;
visibleList = new SortedList<>(MInstitutionInfo.class, new InstitutionListCallback());
allItems = new ArrayList<>();
}
// inflate your list item view here
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.listitem_institution, parent, false);
return new InstitutionViewHolder(view);
}
// on binding, you populate your list item with the values, onclickhandle, etc
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
InstitutionViewHolder institutionViewHolder = (InstitutionViewHolder) viewHolder;
final MInstitutionInfo institutionInfo = visibleList.get(position);
institutionViewHolder.setInstitutionInfo(institutionInfo);
institutionViewHolder.populateTextView();
institutionViewHolder.parent.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
presenter.onInstitutionSelected(institutionInfo);
}
});
}
#Override
public int getItemCount() {
return visibleList.size();
}
// my utility function for the presenter/fragment
public MInstitutionInfo get(int position) {
return visibleList.get(position);
}
public int add(MInstitutionInfo item) {
return visibleList.add(item);
}
public int indexOf(MInstitutionInfo item) {
return visibleList.indexOf(item);
}
public void updateItemAt(int index, MInstitutionInfo item) {
visibleList.updateItemAt(index, item);
}
public void addAll(List<MInstitutionInfo> items) {
visibleList.beginBatchedUpdates();
try {
for (MInstitutionInfo item : items) {
visibleList.add(item);
allItems.add(item);
}
} finally {
visibleList.endBatchedUpdates();
}
}
public void addAll(MInstitutionInfo[] items) {
addAll(Arrays.asList(items));
}
public boolean remove(MInstitutionInfo item) {
return visibleList.remove(item);
}
public MInstitutionInfo removeItemAt(int index) {
return visibleList.removeItemAt(index);
}
public void clearVisibleList() {
visibleList.beginBatchedUpdates();
try {
// remove items at end to remove unnecessary array shifting
while (visibleList.size() > 0) {
visibleList.removeItemAt(visibleList.size() - 1);
}
} finally {
visibleList.endBatchedUpdates();
}
}
public void clearAllItemsList() {
allItems.clear();
}
public void filterList(String queryText) {
clearVisibleList();
visibleList.beginBatchedUpdates();
try {
String constraint = queryText.toLowerCase();
for (MInstitutionInfo institutionInfo : allItems) {
if (institutionInfo.getName() != null && institutionInfo.getName().toLowerCase().contains(constraint)) {
visibleList.add(institutionInfo);
}
}
} finally {
visibleList.endBatchedUpdates();
}
}
public void clearFilter() {
if (visibleList.size() == allItems.size()) {
return;
}
clearVisibleList();
visibleList.beginBatchedUpdates();
try {
for (MInstitutionInfo institutionInfo : allItems) {
visibleList.add(institutionInfo);
}
} finally {
visibleList.endBatchedUpdates();
}
}
// the callback for the SortedList
// this manages the way in which items are added/removed/changed/etc
// mine is pretty simple
private class InstitutionListCallback extends SortedList.Callback<MInstitutionInfo> {
#Override
public int compare(MInstitutionInfo o1, MInstitutionInfo o2) {
return o1.getName().compareTo(o2.getName());
}
#Override
public void onInserted(int position, int count) {
notifyItemRangeInserted(position, count);
}
#Override
public void onRemoved(int position, int count) {
notifyItemRangeRemoved(position, count);
}
#Override
public void onMoved(int fromPosition, int toPosition) {
notifyItemMoved(fromPosition, toPosition);
}
#Override
public void onChanged(int position, int count) {
notifyItemRangeChanged(position, count);
}
#Override
public boolean areContentsTheSame(MInstitutionInfo oldItem, MInstitutionInfo newItem) {
return oldItem.getName().equals(newItem.getName());
}
#Override
public boolean areItemsTheSame(MInstitutionInfo item1, MInstitutionInfo item2) {
return item1.getName().equals(item2.getName());
}
}
// this is the view holder that is used for the list items
private class InstitutionViewHolder extends RecyclerView.ViewHolder {
public View parent;
public TextView tvName;
public MInstitutionInfo institutionInfo;
public InstitutionViewHolder(View itemView) {
super(itemView);
parent = itemView;
tvName = (TextView) itemView.findViewById(R.id.tv_institution_listitem_name);
}
public MInstitutionInfo getInstitutionInfo() {
return institutionInfo;
}
public void setInstitutionInfo(MInstitutionInfo institutionInfo) {
this.institutionInfo = institutionInfo;
}
public void populateTextView() {
if (tvName != null && institutionInfo != null && institutionInfo.getName() != null) {
tvName.setText(institutionInfo.getName());
}
}
}
You simply instantiate this adapter and assign it to your RecyclerView
myRecyclerView.setAdapter(myAdapter);
When you call any of the batched updates, the list will automatically update itself in the UI. So when you get your initial data, just call addAll(yourData) and the RecyclerView will auto populate the list. When you get updated data, you just call addAll(yourNewData) and the RecyclerView will automatically add new items and remove the new non-existent items leaving you with a fully updated list. You will need to be sure to implement the SorteList.Callback methods compare(...), areContentsTheSame(...), areItemsTheSame(...) properly to ensure that this behaves as you want it to when adding/removing items.
Please let me know if you need any more help. Frankly, this implementation type for updated and sorted data is extremely smooth.