Json Array Same Object Duplicate Times - android

I want to get random photos from unsplash and show in my app. Here's the request url I have formed (works with api_key). random photos from unsplash
I have created my model class according to this structure with getters and setters(omitted) like below:
public class UnsplashImages {
public String imageId;
public String rawImg;
public String fullImg;
public String regularImg;
public String smallImg;
public String thumbImg;
public UnsplashImages() {}
public UnsplashImages(String imageId, String rawImg, String fullImg, String regularImg, String smallImg, String thumbImg) {
this.imageId = imageId;
this.rawImg = rawImg;
this.fullImg = fullImg;
this.regularImg = regularImg;
this.smallImg = smallImg;
this.thumbImg = thumbImg;
}
}
According to the docs, this endpoint will return only one image unless count is specified in request url, so I have added count to be max value (30).
This is the json response I am getting for count value > 1:
[
{
id: "7kWEtC4TZlE",
created_at: "2018-02-12T17:28:19-05:00",
updated_at: "2018-05-18T14:03:44-04:00",
width: 3980,
height: 4975,
color: "#FAC9A7",
description: null,
urls: {
raw: "https://images.unsplash.com/photo-1518474436123-0e44861523f7?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjI4ODUzfQ&s=6d9ef54c8c96afc3fbd6cd9aca9e2cf6",
full: "https://images.unsplash.com/photo-1518474436123-0e44861523f7?ixlib=rb-0.3.5&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjI4ODUzfQ&s=e12d5951d3907a1917eb9c1a1c2b67e4",
regular: "https://images.unsplash.com/photo-1518474436123-0e44861523f7?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&ixid=eyJhcHBfaWQiOjI4ODUzfQ&s=da9be90c5000190c773f31969059fdae",
small: "https://images.unsplash.com/photo-1518474436123-0e44861523f7?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=400&fit=max&ixid=eyJhcHBfaWQiOjI4ODUzfQ&s=7630a6850ad1e87dfd580f5066482ee5",
thumb: "https://images.unsplash.com/photo-1518474436123-0e44861523f7?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=200&fit=max&ixid=eyJhcHBfaWQiOjI4ODUzfQ&s=fb527398e3ee3e8c411674fd0a65ce5b"
},
links: {},
categories: [ ],
sponsored: false,
likes: 54,
liked_by_user: false,
current_user_collections: [ ],
slug: null,
user: {},
exif: {},
location: {},
views: 262012,
downloads: 876
},
{},
.
.
.
}
In my fragment I have done json parsing like below:
String s = Constants.RANDOM_PHOTOS + "&count=30";
Log.d(TAG, "Unsplash Misc URL:\t" + s);
AndroidNetworking.get(s)
.addHeaders("Accept-Version", "v1")
.addHeaders("CLIENT-ID", Constants.UNSPLASH_ACCESS_KEY)
.setTag("Unsplash Scifi req")
.setPriority(Priority.HIGH)
.getResponseOnlyFromNetwork()
.build()
.getAsJSONArray(new JSONArrayRequestListener() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, "Un-Response:\t" + response.toString());
if (response != null){
try {
JSONArray jsonArray = new JSONArray(response.toString());
UnsplashImages images = new UnsplashImages();
for (int m = 0; m < jsonArray.length(); m++){
JSONObject object = jsonArray.getJSONObject(m);
images.setImageId(object.getString("id"));
JSONObject urls = object.getJSONObject("urls");
images.setRawImg(urls.getString("raw"));
images.setFullImg(urls.getString("full"));
images.setRegularImg(urls.getString("regular"));
images.setSmallImg(urls.getString("small"));
images.setThumbImg(urls.getString("thumb"));
objectList.add(images);
adapter.notifyDataSetChanged();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
#Override
public void onError(ANError anError) {
}
});
Here's the adapter code:
public class MiscAdapter extends RecyclerView.Adapter<WallpaperItemViewHolder> {
private static final String TAG = MiscAdapter.class.getSimpleName();
private final Context context;
private List<Object> itemsList;
private UnsplashImages unsplashImages;
public MiscAdapter(Context context, List<Object> itemsList) {
this.context = context;
this.itemsList = itemsList;
}
#Override
public WallpaperItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.wallpaper_items_layout, parent, false);
return new WallpaperItemViewHolder(view);
}
#Override
public void onBindViewHolder(final WallpaperItemViewHolder viewholder, final int position) {
unsplashImages = (UnsplashImages) itemsList.get(position);
Picasso.with(context)
.load(unsplashImages.getRegularImg())
.placeholder(R.drawable.drawer_header_trimmed)
.into(viewholder.wallpaperItemImg);
viewholder.favoriteWP_IV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Favorites favorites = new Favorites();
favorites.setFavoritesId(UUID.randomUUID().toString());
favorites.setLargeImgURL(unsplashImages.getRegularImg());
favorites.setPreviewImgURL(unsplashImages.getRegularImg());
favorites.save();
Log.d(TAG, "Fav id:\t" + favorites.getId());
Toast.makeText(context, "Added to Favorites", Toast.LENGTH_SHORT).show();
}
});
viewholder.setWallPaper_TV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final WallpaperManager wpm = WallpaperManager.getInstance(context);
Picasso.with(context)
.load(((UnsplashImages) itemsList.get(position)).getRegularImg())
.into(new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
try {
wpm.setBitmap(bitmap);
Toast.makeText(context, "Your New Wallpaper Has Been Set", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
Log.d(TAG, "Bitmap Load Failed");
Toast.makeText(context, "Could Not Set Wallpaper...Choose Another", Toast.LENGTH_SHORT).show();
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
Log.d(TAG, "Prep to Load Bitmap");
}
});
}
});
}
#Override
public int getItemCount() {
if (itemsList == null) {
return 0;
}
return itemsList.size();
}
}
The images show in the recyclerview list but instead of different items, the same image is shown 30 times in the list. Is this a problem with my json parsing or something else?.

My apologies for your time. I have fixed this by declaring the new instance of my model class inside the for loop like below:
for (int m = 0; m < jsonArray.length(); m++) {
JSONObject object = jsonArray.getJSONObject(m);
UnsplashImages images = new UnsplashImages(); // this here
images.setImageId(object.getString("id"));
JSONObject urls = object.getJSONObject("urls");
images.setRawImg(urls.getString("raw"));
images.setFullImg(urls.getString("full"));
images.setRegularImg(urls.getString("regular"));
images.setSmallImg(urls.getString("small"));
images.setThumbImg(urls.getString("thumb"));
objectList.add(images);
adapter.notifyDataSetChanged();
}
For future observers, take note. Thank you.

Related

RecyleView showing all items duplicates

I am trying to display posts from a server in listView. So I used recycle-view to achieve that. Everything is working fine except that ll items are displaying twice.
I counted the total fetched items from server, and the count is 5, but adapter.getItemCount is showing 10.
After searching hours on the internet, I tried following :
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
and
homeFragmentAdapter.setHasStableIds(true);
Below is my fragment...
package com.example.projectName;
import static android.content.Context.MODE_PRIVATE;
import static android.webkit.ConsoleMessage.MessageLevel.LOG;
import static com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade;
public class HomeFollowersFragment extends Fragment implements InfiniteScrollListener.OnLoadMoreListener, RecyclerViewItemListener {
private static final String TAG = "HomeFollowersFragment";
private static final String URL = "https://api.androidhive.info/json/movies_2017.json";
private RecyclerView recyclerView;
private ProgressBar postLoader;
FFmpeg ffmpeg;
// private List<Movie> movieList;
// private HomeAdapter mAdapter;
private List<PostList> postListGlobal = new ArrayList<>();
List<VerticalDataModal> verticalDataModals;
List<HorizontalDataModal> horizontalDataModals;
private SwipeRefreshLayout swipeMore;
private InfiniteScrollListener infiniteScrollListener;
private HomeFragmentAdapter homeFragmentAdapter;
SharedPreferences sharedPreferences;
private Boolean isLoggedIn = false;
private String email = "";
private String token = "";
private String userId = "";
private Dialog customLoader;
SkeletonScreen skeletonScreen;
private int pastVisiblesItems, visibleItemCount, totalItemCount;
private boolean loading = false;
private EndlessScrollListener scrollListener;
SharedPreferences sp;
SharedPreferences.Editor Ed;
public HomeFollowersFragment() {
//super();
}
/**
* #return A new instance of fragment HomeFollowersFragment.
*/
public static HomeFollowersFragment newInstance() {
return new HomeFollowersFragment();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#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);
// ((AppCompatActivity) getActivity()).getSupportActionBar().show();
try{
sharedPreferences = getActivity().getSharedPreferences("Login", MODE_PRIVATE);
email = sharedPreferences.getString("email", null);
token = sharedPreferences.getString("token", null);
isLoggedIn = sharedPreferences.getBoolean("isLoggedIn", false);
userId = sharedPreferences.getString("id", null);
}catch (Exception e){
e.printStackTrace();
Log.d("StackError", "StackError: "+e);
}
sp = getActivity().getSharedPreferences("Posts", MODE_PRIVATE);
if(!isLoggedIn || token == null || userId == null){
Intent intent = new Intent(getActivity(), RegisterActivity.class);
intent.putExtra("loginFrom", "profile");
startActivity(intent);
}
recyclerView = view.findViewById(R.id.recycler_view);
postLoader = view.findViewById(R.id.post_loader);
swipeMore = view.findViewById(R.id.swipe_layout);
homeFragmentAdapter = new HomeFragmentAdapter(postListGlobal, this, "home");
if(sp.contains("postListGlobal"))
skeletonScreen = Skeleton.bind(recyclerView)
.adapter(homeFragmentAdapter)
.shimmer(true)
.angle(20)
.frozen(false)
.duration(1200)
.count(10)
.load(R.layout.item_skelton_home_page)
.show(); //default count is 10
RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(getActivity(), 2);
StaggeredGridLayoutManager sLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(sLayoutManager);
homeFragmentAdapter.setHasStableIds(true);
recyclerView.setAdapter(homeFragmentAdapter);
recyclerView.setNestedScrollingEnabled(false);
customLoader = new Dialog(getActivity(), R.style.crystal_range_seek_bar);
customLoader.setCancelable(false);
View loaderView = getLayoutInflater().inflate(R.layout.custom_loading_layout, null);
customLoader.getWindow().getAttributes().windowAnimations = R.style.crystal_range_seek_bar;
customLoader.getWindow().setBackgroundDrawableResource(R.color.translucent_black);
ImageView imageLoader = loaderView.findViewById(R.id.logo_loader);
Glide.with(this).load(R.drawable.logo_loader).into(imageLoader);
customLoader.setContentView(loaderView);
if(homeFragmentAdapter.getItemCount() == 0 && !loading){
// server fetchdata
Log.d(TAG, "no item available..");
postLoader.setVisibility(View.VISIBLE);
loading = true;
fetchStoreItems();
}else{
postLoader.setVisibility(View.GONE);
}
swipeMore.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
Log.d(TAG, "on refresh...");
fetchStoreItems();
}
});
return view;
}
#Override
public void onItemClicked(int position) {
Log.d(TAG, "click position: "+position);
Toast.makeText(getActivity(),postListGlobal.get(position).getTitle(),Toast.LENGTH_SHORT).show();
// Toast.makeText(getActivity(),""+position, Toast.LENGTH_SHORT).show();
}
public int getLastVisibleItem(int[] lastVisibleItemPositions) {
int maxSize = 0;
for (int i = 0; i < lastVisibleItemPositions.length; i++) {
if (i == 0) {
maxSize = lastVisibleItemPositions[i];
}
else if (lastVisibleItemPositions[i] > maxSize) {
maxSize = lastVisibleItemPositions[i];
}
}
return maxSize;
}
#Override
public void onLoadMore() {
homeFragmentAdapter.addNullData();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
homeFragmentAdapter.removeNull();
Toast.makeText(getContext(), "load more here...", Toast.LENGTH_LONG).show();
// fetchStoreItems();
swipeMore.setRefreshing(false);
}
}, 2000);
}
private void fetchStoreItems() {
RequestQueue queue = Volley.newRequestQueue(getActivity());
Log.d(TAG, "Post Data Followers: "+Constant.FETCH_POSTS_API);
CacheRequest cacheRequest = new CacheRequest(0, Constant.FETCH_POSTS_API, new Response.Listener<NetworkResponse>() {
#Override
public void onResponse(NetworkResponse response) {
try {
final String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
if (response == null) {
Toast.makeText(getActivity(), "Couldn't fetch the store items! Pleas try again.", Toast.LENGTH_LONG).show();
loading = false;
return;
}
JSONObject postObj = new JSONObject(jsonString);
System.out.println("post full data... : " + postObj);
if (postObj.getBoolean("Status")) {
try {
postLoader.setVisibility(View.GONE);
JSONArray arrayResponse = postObj.optJSONArray("Data");
int dataArrLength = arrayResponse.length();
if(dataArrLength == 0){
Toast.makeText(getActivity(), "No posts available at this time, you can create yout own post by clicking on mic button", Toast.LENGTH_SHORT).show();
}
postListGlobal.clear();
Log.d(TAG, "Total Posts count: "+dataArrLength);
for(int i=0; i<dataArrLength; i++) {
try {
JSONObject dataListObj = arrayResponse.optJSONObject(i);
System.out.println("post full data... : " + dataListObj);
JSONObject postDetailObj = dataListObj.optJSONObject("post_detail");
JSONObject followDtatusObj = dataListObj.optJSONObject("follow_status");
JSONArray postFilesArr = dataListObj.optJSONArray("post_files");
JSONObject userDatasObj = postDetailObj.optJSONObject("user");
String userId = userDatasObj.optString("id");
String userName = userDatasObj.optString("email");
String userImage = userDatasObj.optString("email");
boolean followStatus = followDtatusObj.optBoolean("follow");
String postId = postDetailObj.optString("id");
String postTitle = postDetailObj.optString("post_title");
String postDescription = postDetailObj.optString("post_description");
String postCoverUrl = postDetailObj.optString("post_coverurl", "1");
String postViewType = postDetailObj.optString("view_type", "1");
String postAllowComment = postDetailObj.optString("allow_comments", "1");
String postAllowDownload = postDetailObj.optString("allow_download", "1");
String postTotalPost = postDetailObj.optString("total_post", "1");
String postPostSection = postDetailObj.optString("post_section", "image");
String postActiveStatus = postDetailObj.optString("is_active", "1");
String postTotalViews = postDetailObj.optString("total_watched","0");
String postTotalShare = postDetailObj.optString("total_share","0");
String postTotalDownload = postDetailObj.optString("total_download","0");
String postTotalReaction = postDetailObj.optString("total_reaction","0");
String postTotalLike = postDetailObj.optString("total_like","0");
String postTotalSmile = postDetailObj.optString("smile_reaction","0");
String postTotalLaugh = postDetailObj.optString("laugh_reaction","0");
String postTotalSad = postDetailObj.optString("sad_reaction","0");
String postTotalLove = postDetailObj.optString("love_reaction","0");
String postTotalShock = postDetailObj.optString("shock_reaction","0");
int totalPostFiles = Integer.parseInt(postTotalPost);
int postArrLength = postFilesArr.length();
String postImageUrl = null;
String postMusicUrl = null;
String commonUrl = "http://serverName.com/";
if(postArrLength >= 1){
JSONObject dataFilesListObj = postFilesArr.optJSONObject(0);
// System.out.println("post files full data... : " + dataFilesListObj);
String postFileId = dataFilesListObj.optString("id");
postImageUrl = dataFilesListObj.optString("image_file_path");
postMusicUrl = dataFilesListObj.optString("music_file_path");
System.out.println("post files full data... : " + dataFilesListObj);
}
System.out.println("post files full data... : " + commonUrl+postMusicUrl);
System.out.println("post files full data... : " + commonUrl+postImageUrl);
PostList postList = new PostList();
postList.setId(postId);
postList.setTitle(postTitle);
postList.setTotalPost(""+dataArrLength);
postList.setTotalView(postTotalViews);
postList.setTotalReaction(postTotalReaction);
postList.setMusicPath(commonUrl+postMusicUrl);
postList.setImagePath(commonUrl+postImageUrl);
if(postImageUrl == null){
postList.setImagePath("https://amazonBucket.s3.location.amazonaws.com/images/pic1.jpg");
}
postList.setUserId(userId);
postList.setUserName(userName);
postList.setPostDataObject(arrayResponse);
postListGlobal.add(postList);
Log.d(TAG, "Total Posts: "+dataListObj);
} catch (Exception e) {
e.printStackTrace();
Log.d(TAG, "Post Data Error1: "+e);
Toast.makeText(getActivity(), "File now found", Toast.LENGTH_LONG).show();
loading = false;
}
}
} catch (Exception e){
e.printStackTrace();
Log.d(TAG, "Post Data Error2: "+e);
Toast.makeText(getActivity(), R.string.server_error, Toast.LENGTH_LONG).show();
loading = false;
}
}else{
try {
Toast.makeText(getActivity(), new JSONObject(jsonString).getString("Message"), Toast.LENGTH_LONG).show();
} catch (JSONException ex) {
ex.printStackTrace();
Log.d(TAG, "Post Data Error3: "+ex);
Toast.makeText(getActivity(), R.string.server_error, Toast.LENGTH_SHORT).show();
}
loading = false;
}
// refreshing recycler view
homeFragmentAdapter.removeNull();
homeFragmentAdapter.addData(postListGlobal);
homeFragmentAdapter.notifyDataSetChanged();
// save in local memory
// saveArrayList(postListGlobal, "postListGlobal");
} catch (Exception e) {
e.printStackTrace();
Log.d(TAG, "Post Data Error4: "+e);
}
loading = true;
homeFragmentAdapter.notifyDataSetChanged();
swipeMore.setRefreshing(false);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getActivity(), "onErrorResponse: "+ error, Toast.LENGTH_SHORT).show();
swipeMore.setRefreshing(false);
loading = true;
homeFragmentAdapter.notifyDataSetChanged();
postLoader.setVisibility(View.VISIBLE);
loading = false;
Log.d(TAG, "Post Data Error5: "+error);
}
}){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
String finalToken = "Bearer "+token;
params.put("Authorization", finalToken);
params.put("Content-Type", "application/json");
return params;
}
};
// Add the request to the RequestQueue.
queue.add(cacheRequest);
}
private class CacheRequest extends Request<NetworkResponse> {
private final Response.Listener<NetworkResponse> mListener;
private final Response.ErrorListener mErrorListener;
public CacheRequest(int method, String url, Response.Listener<NetworkResponse> listener, Response.ErrorListener errorListener) {
super(method, url, errorListener);
this.mListener = listener;
this.mErrorListener = errorListener;
}
#Override
protected Response<NetworkResponse> parseNetworkResponse(NetworkResponse response) {
Cache.Entry cacheEntry = HttpHeaderParser.parseCacheHeaders(response);
if (cacheEntry == null) {
cacheEntry = new Cache.Entry();
}
final long cacheHitButRefreshed = 3 * 60 * 1000; // in 3 minutes cache will be hit, but also refreshed on background
final long cacheExpired = 24 * 60 * 60 * 1000; // in 24 hours this cache entry expires completely
long now = System.currentTimeMillis();
final long softExpire = now + cacheHitButRefreshed;
final long ttl = now + cacheExpired;
cacheEntry.data = response.data;
cacheEntry.softTtl = softExpire;
cacheEntry.ttl = ttl;
String headerValue;
headerValue = response.headers.get("Date");
if (headerValue != null) {
cacheEntry.serverDate = HttpHeaderParser.parseDateAsEpoch(headerValue);
}
headerValue = response.headers.get("Last-Modified");
if (headerValue != null) {
cacheEntry.lastModified = HttpHeaderParser.parseDateAsEpoch(headerValue);
}
cacheEntry.responseHeaders = response.headers;
return Response.success(response, cacheEntry);
}
#Override
protected void deliverResponse(NetworkResponse response) {
mListener.onResponse(response);
}
#Override
protected VolleyError parseNetworkError(VolleyError volleyError) {
Log.d(TAG, "Post Data volleyError: "+volleyError);
return super.parseNetworkError(volleyError);
}
#Override
public void deliverError(VolleyError error) {
mErrorListener.onErrorResponse(error);
}
}
}
and Adapter Class
package com.example.ProjectName;
public class HomeFragmentAdapter extends RecyclerView.Adapter <HomeFragmentAdapter.HomeViewHolder>{
// private ArrayList<Integer> dataList;
private List<PostList> postListGlobal;
int VIEW_TYPE_LOADING;
int VIEW_TYPE_ITEM;
Context context;
private RecyclerViewItemListener callback;
FFmpeg ffmpeg;
String callingPage;
public HomeFragmentAdapter(List<PostList> postListGlobal, RecyclerViewItemListener callback, String callingPage) {
this.postListGlobal = postListGlobal;
this.callback = callback;
this.callingPage = callingPage;
// setHasStableIds(true);
}
#NonNull
#Override
public HomeFragmentAdapter.HomeViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View root = null;
context = parent.getContext();
root = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_home_tile_list, parent, false);
return new DataViewHolder(root);
}
#Override
public void onBindViewHolder(#NonNull HomeFragmentAdapter.HomeViewHolder holder, int position) {
if (holder instanceof DataViewHolder) {
final PostList postList = postListGlobal.get(position);
holder.postTitle.setText(postList.getTitle());
holder.postWatch.setText(postList.getTotalView());
holder.postReaction.setText(postList.getTotalReaction());
String imageUrl = postList.getImagePath();
// String imageUrl = Constant.SERVER_URL+"/"+postList.getImagePath();
String musicUrl = postList.getMusicPath();
// String musicUrl = Constant.SERVER_URL+"/"+postList.getMusicPath();
Log.d(TAG, "Post url: "+imageUrl+" -- "+musicUrl);
// int totalMusicTime = getDurationVal(musicUrl, "second");
holder.postTime.setText(postList.getTotalPost());
holder.thumbnail.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
callback.onItemClicked(position);
Log.d("homeView", "screenName : "+callingPage);
if(callingPage.equals("home")){
Log.d("homeView", "screenName : "+position);
Intent intent = new Intent(context, MainViewActivity.class);
intent.putExtra("loginFrom", "homeView");
intent.putExtra("postDataObj", postList.getPostDataObject().toString());
intent.putExtra("postPosition", ""+position);
intent.putExtra("tabId", "1");
context.startActivity(intent);
}
}
});
Drawable mDefaultBackground = context.getResources().getDrawable(R.drawable.influencers);
CircularProgressDrawable circularProgressDrawable = new CircularProgressDrawable(context);
circularProgressDrawable.setStrokeWidth(5f);
Glide.with(context)
.load(imageUrl)
.listener(new RequestListener<Drawable>() {
#Override
public boolean onLoadFailed(#Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
// progressBar.setVisibility(View.GONE);
return false;
}
#Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
// progressBar.setVisibility(View.GONE);
return false;
}
})
.error(mDefaultBackground)
.into(holder.thumbnail);
}else{
//Do whatever you want. Or nothing !!
}
}
#Override
public int getItemCount() {
return postListGlobal.size();
}
class DataViewHolder extends HomeViewHolder {
public DataViewHolder(View itemView) {
super(itemView);
}
}
class ProgressViewHolder extends HomeViewHolder {
public ProgressViewHolder(View itemView) {
super(itemView);
}
}
class HomeViewHolder extends RecyclerView.ViewHolder {
public TextView postTitle, postTime, postWatch, postReaction;
public ImageView thumbnail;
public HomeViewHolder(View itemView) {
super(itemView);
postTitle = itemView.findViewById(R.id.post_title);
postTime = itemView.findViewById(R.id.total_time);
postWatch = itemView.findViewById(R.id.total_watch);
postReaction = itemView.findViewById(R.id.total_reaction);
thumbnail = itemView.findViewById(R.id.thumbnail);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
public void addNullData() {
}
public void removeNull() {
notifyItemRemoved(postListGlobal.size());
}
public void addData(List<PostList> postLists) {
postListGlobal.addAll(postLists);
notifyDataSetChanged();
}
}
After trying everything, I was still not able to resolve the issue. Any help/suggestions are welcome. Let me know If I left out any needed code--if so I can update it here.
`postListGlobal.add(postList);` below this line add ` homeFragmentAdapter.notifyDataSetChanged();` and remove ` homeFragmentAdapter.removeNull(); homeFragmentAdapter.addData(postListGlobal);homeFragmentAdapter.notifyDataSetChanged();` this code.Because in this case list added twice without notifying datasetchange check with your code by removing this.
postListGlobal.clear(); just clear tha arraylist before add .
postListGlobal.clear() before adding new list to the adapter.
And then notifyDataSetChanged() to let adapter know of the changes.

How to update array adapter using timer/handler?

I get the data from API such as printer name, model and status and displaying in the listview in array adapter.In my program I am testing if the printer is idle or not and showing by using green(idle) and red (busy) circles in the listview , but my issue is that the state has to be constantly checked and get updated to display on screen green or red circle, for this case I was checking out into handler and timers and tried to implement it but unsuccessfully - nothing worked. I am unsure which one is better to use and how , since I am using array adapter.
If you have any insights, please let me know.
My adapter class:
public class NsdServiceInfoAdapter extends ArrayAdapter<PrinterNew> {
private Context mContext;
private List<PrinterNew> services;
private InetAddress hostAddress;
//Creating new constructor with parameters such as this class(context), layout id (list item layout Id) and data model.
public NsdServiceInfoAdapter(#NonNull Context context, int layoutId, List<PrinterNew> list) {
super(context, layoutId, list);
mContext = context;
services = list;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull
ViewGroup parent) {
View listItem = convertView;
//Checking if view is empty then we inflate our list layout.
if (listItem == null)
listItem =
LayoutInflater.from(mContext).inflate(R.layout.list_item, parent, false);
//Getting data's position in the data set.
final PrinterNew currentService = services.get(position);
final ImageView i = listItem.findViewById(R.id.status_circle);
TextView t = listItem.findViewById(R.id.TextView_serviceName);
final TextView r = listItem.findViewById(R.id.TextView_serviceIP);
r.setText(currentService.getPrinterModel());
t.setText(currentService.getPrinterName());
if (currentService.isIdle()) {
i.setColorFilter(Color.rgb(42, 187, 155));
} else {
i.setColorFilter(Color.rgb(240, 52, 52));
}
return listItem;
}
}
My printer class
public PrinterNew() {
}
public String getPrinterName() {
return printerName;
}
public void setPrinterName(String printerName) {
this.printerName = printerName;
}
public String getPrinterModel() {
return printerModel;
}
public String getPrinterInformation() {
return this.printInformation;
}
public void setPrinterInformation(String url, Context context, final VolleyCallback callback) {
Log.d("API", "Currently calling URL " + url);
RequestQueue queue = Volley.newRequestQueue(context);
queue.add(new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d("API", "Print information" + response);
String temp = response.substring(2, response.length() - 2);
byte msgArray[];
try {
msgArray = temp.getBytes("ISO-8859-1");
state = msgArray[0];
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
printInformation = response;
callback.onSuccess(printInformation);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("API", "Print information nope ");
callback.onFailure(error);
}
}));
}
public String getMenuInformation() {
return menuInformation;
}
public void setMenuInformation(String url, Context context, final VolleyCallback callback) {
Log.d("API", "Currently calling URL " + url);
RequestQueue queue = Volley.newRequestQueue(context);
queue.add(new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
String temp = response.substring(2, response.length() - 2);
Log.d("API", "Current menu" + response);
byte msgArray[];
try {
msgArray = temp.getBytes("ISO-8859-1");
currentMenu = msgArray[0];
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
menuInformation = response;
callback.onSuccess(menuInformation);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("API", "Current menu Nope ");
callback.onFailure(error);
}
}));
}
public boolean isIdle() {
if (state == -1 && currentMenu == 0) {
return true;
} else {
return false;
}
}
public void setPrinterService(NsdServiceInfo service) {
this.printerService = service;
}
public NsdServiceInfo getPrinterService() {
return this.printerService;
}
public interface VolleyCallback {
void onSuccess(String result);
void onFailure(Object response);
}
public void setPrinterModel(String url, Context context, final VolleyCallback callback) {
Log.d("API", "Currently calling URL " + url);
RequestQueue queue = Volley.newRequestQueue(context);
queue.add(new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("API", "printer model nope ");
callback.onFailure(error);
}
}));
}
}
use recyclerview.
to refresh your list whenever there is data change in the list with recyclerview, you need to user adapter.notifyDataSetChanged()
but catch here is you need to get exact object in the list, the update it then refresh it with above line.
Hope this helps.

Store all the information at once using Realm in Background thread Android

I am developing an android app, where I am using Relam as local Database. I have rest api one for all the user information and other is for news information. I have two buttons. one for showing the user information and other is for showing the news information. Now, with my code what is done, after login, I need to click the button at first for user information and news information accordingly and then I can see those images and news. but if I connection off, just after login, the data is not showing in the view. I am explaining my code in detail.Also I am having problem in image loading. How can I Make the funtionality so that user can get all the information just after login.I am reallly sorry for such a long code. It would be really helpful for me if someone tell me how can I modify my code to store all data in background thread, so that user get all information just after login.
The part of the login page where I want to start
private void loginUser(final String mEmail, final String mPassword) {
final GlobalClass globalClass = new GlobalClass();
globalClass.setEmail_info( mEmail );
setFilePath();
RequestQueue queue = Volley.newRequestQueue( LoginPage.this );
StringRequest strReq = new StringRequest( Request.Method.POST,
LOGIN_URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d( TAG, "Register Response: " + response.toString() );
//parse your response here
if (response.contains( "overview" )) {
showProgress( true );
globalClass.setImage_urlpath( Constants.HTTP.PHOTO_URL + mEmail);
String str = globalClass.readDatafromStorage();
Log.d("----After Login---",str);
if ( !str.contains("ACTIVATE") ) {
Log.d( "----After Login---", "After Login" );
}
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(KEY_EMAIL, mEmail);
editor.putString(KEY_PASSWORD, mPassword);
editor.commit();
showProgress(false);
Intent loginIntent = new Intent(LoginPage.this, MainOptionPage.class);
loginIntent.putExtra(KEY_EMAIL, mEmail);
startActivity(loginIntent);
} else {
userEmail.setError(getString(R.string.error_incorrect_login));
userEmail.requestFocus();
}
}
}, new Response.ErrorListener() {
#Override
....
Here is my code for User Page
public class MyColleaguesPage extends AppCompatActivity implements ColleagueController.UserCallbackListener {
private List<MyColleagueModel> myColleagueList = new ArrayList<>();
private Realm colleagueRealm;
private RealmResults<MyColleagueModel> colleagueResult;
private List<MyColleagueModel> filteredModelList;
private RealmChangeListener realmListener;
private static final String DIALOG_TAG = "EmployeeDialog";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mycolleagues_layout);
configViews();
}
private void configViews() {
recyclerView = this.findViewById(R.id.colleagues_recycler);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(MyColleaguesPage.this));
recyclerView.setRecycledViewPool(new RecyclerView.RecycledViewPool());
colleagueRealm = Realm.getDefaultInstance();
RealmResults<MyColleagueModel> results = colleagueRealm.where(MyColleagueModel.class).findAll();
for (int i = 0; i < results.size(); i++) {
myColleagueList.add(results.get(i));
}
adapter = new MyColleaguesAdapter(myColleagueList,getApplicationContext());
//adapter = new MyColleaguesAdapter(myColleagueList,getApplicationContext());
Log.d( "adapter value is"+"", String.valueOf( adapter ) );
recyclerView.setAdapter(adapter);
}
//successful
#Override
public void onFetchStart() {
}
#Override
public void onFetchProgress(ColleagueModel colleague) {
//adapter.addColleague(colleague);
}
#Override
public void onFetchProgress(List<ColleagueModel> colleagueList) {
}
#Override
public void onFetchComplete() {
}
#Override
public void onFetchFailed() {
}
}
Here is my controller class for my colleague page
public class ColleagueController {
private static final String TAG = ColleagueController.class.getSimpleName();
private UserCallbackListener mListener;
private ColleagueResApiManager mApiManager;
Realm myColleague_realm;
public ColleagueController() {
mApiManager = new ColleagueResApiManager();
}
public void startFetching(){
myColleague_realm = Realm.getDefaultInstance();
mApiManager.getColleagueApi().getColleague(new Callback<String>() {
#Override
public void success(String s, Response response) {
Log.d(TAG, "JSON :: " + s);
try {
JSONArray array = new JSONArray(s);
for(int i = 0; i < array.length(); i++) {
JSONObject object = array.getJSONObject(i);
Log.d("-----Start Fetching---", object.optString( "name" ));
myColleague_realm.beginTransaction();
MyColleagueModel mycolleague = myColleague_realm.createObject( MyColleagueModel.class );
mycolleague.setName( object.optString( "name" ) );
.... data ) );
myColleague_realm.commitTransaction();
}
} catch (JSONException e) {
mListener.onFetchFailed();
}
// mListener.onFetchComplete();
}
#Override
public void failure(RetrofitError error) {
Log.d(TAG, "Error :: " + error.getMessage());
if (mListener != null) {
mListener.onFetchComplete();
}
}
});
}
public interface UserCallbackListener{
void onFetchComplete();
void onFetchFailed();
}
}
In the same way I have other page news option page where I am shoing the news data. Here is my news page.
public class NewsPage extends AppCompatActivity{
private RecyclerView recyclerView;
private NewsAdapter adapter;
private Realm newsRealm;
private List<NewsRealmModel> mNewsList;
private List<NewsRealmModel> filteredModelList;
private NewsController mController;
Constant constant;
SharedPreferences app_preferences;
int appTheme;
int themeColor;
int appColor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView( R.layout.news_page_layout);
configViews();
}
private void configViews() {
recyclerView = this.findViewById(R.id.news_recycler);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(NewsPage.this));
recyclerView.setRecycledViewPool(new RecyclerView.RecycledViewPool());
Realm newsRealm = Realm.getDefaultInstance();
RealmResults<NewsRealmModel> temp = newsRealm.where(NewsRealmModel.class).findAll();
mNewsList = new ArrayList<>();
for (int i = 0; i < temp.size(); i++) {
mNewsList.add(temp.get(i));
}
adapter = new NewsAdapter(mNewsList,getApplicationContext());
Log.d( "adapter value is"+"", String.valueOf( adapter ) );
recyclerView.setAdapter(adapter);
}
}
And the new Controller Class
public class NewsController {
private static final String TAG = NewsController.class.getSimpleName();
private UserCallbackListener mListener;
private NewsRestApiManager mApiManager;
private AppImage appImages;
Realm myNews_realm;
ArrayList<String> title_list = new ArrayList<>();
GlobalClass globalClass = new GlobalClass();
public NewsController(UserCallbackListener listener) {
mListener = listener;
mApiManager = new NewsRestApiManager();
}
public void startFetching() {
myNews_realm = Realm.getDefaultInstance();
mApiManager.getNewsApi().getNews(new Callback<String>() {
#Override
public void success(String s, Response response) {
Log.d(TAG, "JSON :: " + s);
try {
JSONArray array = new JSONArray(s);
for (int i = 0; i < array.length(); i++) {
JSONObject jsonObject = array.getJSONObject(i);
Log.d("-----Start Fetching---", jsonObject.optString("title"));
if (!myNews_realm.isInTransaction()) {
myNews_realm.beginTransaction();
NewsRealmModel news = new NewsRealmModel();
....... data
}
myNews_realm.copyToRealm(news);
myNews_realm.commitTransaction();
mListener.onFetchProgressNews(news);
} else {
myNews_realm.commitTransaction();
}
}
} catch (JSONException e) {
mListener.onFetchFailed();
}
mListener.onFetchComplete();
}
#Override
public void failure(RetrofitError error) {
Log.d(TAG, "Error :: " + error.getMessage());
mListener.onFetchComplete();
}
});
}
public interface UserCallbackListener {
void onFetchProgressNews(NewsRealmModel news);
void onFetchComplete();
void onFetchFailed();
}
}
To do your database processing on a background thread using Volley, you need to extend Request<T> and do the Realm write in parseNetworkResponse method.
public class RealmGsonObjectRequest<T, M extends RealmModel> extends Response<Void> {
...
#Override
protected Response<Void> parseNetworkResponse(
NetworkResponse response) {
try {
String json = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
T data = gson.fromJson(json, clazz);
// write the downloaded data into the Realm on bg thread
try(Realm r = Realm.getDefaultInstance()) {
M model = mapper.toModel(data);
r.executeTransaction((realm) -> {
realm.insertOrUpdate(model);
});
}
return Response.success(null,
HttpHeaderParser.parseCacheHeaders(response)
);
} // handle errors
}
You might need a RealmGsonListRequest as well.
public class RealmGsonListRequest<T, M extends RealmModel> extends Response<Void> {
...
#Override
protected Response<Void> parseNetworkResponse(
NetworkResponse response) {
try {
String json = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
List<T> data = gson.fromJson(json, new TypeToken<ArrayList<T>>() {}.getType());
// write the downloaded data into the Realm on bg thread
try(Realm r = Realm.getDefaultInstance()) {
M model = mapper.toModel(data);
r.executeTransaction((realm) -> {
realm.insertOrUpdate(model);
});
}
return Response.success(null,
HttpHeaderParser.parseCacheHeaders(response)
);
} // handle errors
}
For more information, refer to the official Volley tutorial on how to create a custom Volley request type.

Cant access viewHolder in a customArrayadapter in another function?

I am creating an application with a list that list cards based on the value from the server.
I created a StudentCardArrayAdapter to achieve this and everything works fine. All the data has been populated in card list. also I able to get the values on button click in each card separately.
What I need is on clicking the button it will call a method requestion server for data asynchronously and get a value from the server and according to that value, i need to change the button text in that particular card.
My StudentCardArrayAdapter code:
public class StudentCardArrayAdapter extends ArrayAdapter<StudentCard> {
private static final String TAG = "CardArrayAdapter";
private List<StudentCard> cardList = new ArrayList<StudentCard>();
private Context mContext;
String selected = "0";
PreferenceHelper prefs;
CardViewHolder viewHolder;
View row;
ProgressDialog pd;
static class CardViewHolder {
TextView studentname;
TextView stop;
Button selectbutton;
CircleImageView imageId;
}
public StudentCardArrayAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
this.mContext = context;
prefs = new PreferenceHelper(this.mContext);
pd = new ProgressDialog(this.mContext);
}
#Override
public void add(StudentCard object) {
cardList.add(object);
super.add(object);
}
#Override
public int getCount() {
return this.cardList.size();
}
#Override
public StudentCard getItem(int index) {
return this.cardList.get(index);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
row = convertView;
if (row == null) {
LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.student_card, parent, false);
viewHolder = new CardViewHolder();
viewHolder.studentname = (TextView) row.findViewById(R.id.studentname);
viewHolder.stop = (TextView) row.findViewById(R.id.stop);
viewHolder.selectbutton = (Button) row.findViewById(R.id.selectbutton);
viewHolder.imageId = (CircleImageView) row.findViewById(R.id.imageId);
row.setTag(viewHolder);
} else {
viewHolder = (CardViewHolder)row.getTag();
}
StudentCard card = getItem(position);
viewHolder.studentname.setText(card.getStudName());
viewHolder.studentname.setTextColor(Color.parseColor("#000000"));
viewHolder.stop.setText(card.getStudStop());
viewHolder.stop.setTextColor(Color.parseColor("#000000"));
if(card.getSelected().equals("1")){
viewHolder.selectbutton.setText(mContext.getResources().getString(R.string.selected));
viewHolder.selectbutton.setEnabled(false);
}
else{
viewHolder.selectbutton.setText(mContext.getResources().getString(R.string.select));
viewHolder.selectbutton.setEnabled(true);
}
final String studid = card.getStudId();
final String busname = prefs.getString("busname", "0");
final String schoolid = prefs.getString("schoolid", "");
viewHolder.selectbutton.setOnClickListener(new View.OnClickListener()
{
String updatedvalue = "0";
#Override
public void onClick(View v)
{
Log.e("studid",studid);
Log.e("busname",busname);
Log.e("schoolid",schoolid);
selectstudent(v, studid, busname, schoolid,mContext);
//Toast.makeText(v.getContext(), amountinfo, Toast.LENGTH_SHORT).show();
/*SnackbarManager.show(Snackbar.with(this) // context
.text(amountinfo));*/
}
});
Picasso.with(mContext).load(card.getImageUrl()).fit().error(R.mipmap.ic_launcher).into(viewHolder.imageId);
return row;
}
public void selectstudent(final View v, String studid, String busname, String schoolid, final Context mContext) {
String returnedselected = "0";
Log.e("BASE_URL_STUDENT_UPDATE", Constants.BASE_URL_STUDENT_UPDATE + "?studid=" + studid+"&busname="+busname+"&schoolid="+schoolid);
RestClientHelper.getInstance().get(Constants.BASE_URL_STUDENT_UPDATE + "?studid=" + studid+"&busname="+busname+"&schoolid="+schoolid, new RestClientHelper.RestClientListener() {
#Override
public void onSuccess(String response) {
Log.e("RESULT", response);
try {
JSONObject result = new JSONObject(response);
JSONArray posts = result.optJSONArray("status");
for (int i = 0; i < posts.length(); i++) {
JSONObject post = posts.optJSONObject(i);
String status = post.optString("status");
if (status.equals("true")) {
selected = post.optString("selected");
} else {
selected = post.optString("selected");
String error = post.optString("error");
SnackbarManager.show(Snackbar.with(getContext()) // context
.text(error));
}
}
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
} finally {
if(selected.equals("1")){
viewHolder.selectbutton.setText(mContext.getResources().getString(R.string.selected));
viewHolder.selectbutton.setEnabled(false);
}
}
}
#Override
public void onError(String error) {
Log.e("error", error);
selected = "0";
}
});
}
}
I used the below code but nothing works.. No error also.. and not change in button text.I get value of selected as 1 from server.
if(selected.equals("1")){
viewHolder.selectbutton.setText(mContext.getResources().getString(R.string.selected));
viewHolder.selectbutton.setEnabled(false);
}
I am new to android.. and is stuck here. Please help me out.
FINALLY IT WORKED
As changes mention by Krish, I updated the code suggested by him.
And added this changes in onClick it worked
if(card.getSelected().equals("1")){
viewHolder.selectbutton.setText(mContext.getResources().getString(R.string.selected));
viewHolder.selectbutton.setEnabled(false);
}
Change the code like this,
public void selectstudent(StudentCard card, String studid, String busname, String schoolid, final Context mContext) {
String returnedselected = "0";
Log.e("BASE_URL_STUDENT_UPDATE", Constants.BASE_URL_STUDENT_UPDATE + "?studid=" + studid+"&busname="+busname+"&schoolid="+schoolid);
RestClientHelper.getInstance().get(Constants.BASE_URL_STUDENT_UPDATE + "?studid=" + studid+"&busname="+busname+"&schoolid="+schoolid, new RestClientHelper.RestClientListener() {
#Override
public void onSuccess(String response) {
Log.e("RESULT", response);
try {
JSONObject result = new JSONObject(response);
JSONArray posts = result.optJSONArray("status");
for (int i = 0; i < posts.length(); i++) {
JSONObject post = posts.optJSONObject(i);
String status = post.optString("status");
if (status.equals("true")) {
selected = post.optString("selected");
} else {
selected = post.optString("selected");
String error = post.optString("error");
SnackbarManager.show(Snackbar.with(getContext()) // context
.text(error));
}
}
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
} finally {
if(selected.equals("1")){
card.setSelected("1");
notifyDataSetChanged();
}
}
}
#Override
public void onError(String error) {
Log.e("error", error);
selected = "0";
}
});
}
and change this line like this ,
final StudentCard card = getItem(position);
and call method inside onclick.
selectstudent(card, studid, busname, schoolid,mContext);

Android Json and RecyclerView is not clickable, MultiLevel problems

I am still not confident working with android and I have 2 problems here, I would like to make Multi level recyclerView with 3 levels. 1st level is categories RecyclerView, 2nd is ListView with list of exercises and 3rd level is details. So now I made a 1st level recyclerView which is not clickable. Another problem is how to fetch Listview in 2nd level to the details of the 3rd level? Here is my code of 1st level fragment:
public class BallTrainingFragment extends Fragment {
View mRootView;
String URL_TO_HIT = "https://gist.githubusercontent.com/tomasmaks/afbf3e836dabd72c95c4b3ec90e291ed/raw/7ba41948865f78f1ccb4058c61f8c6e06c601300/BasketballTraining.json";
BallTrainingAdapter adapter;
RecyclerView mRecyclerView;
private List<BallTrainingModel> ballTraining;
GridLayoutManager mGridLayoutManager;
public BallTrainingFragment() {
// Required empty public constructor
}
public static BallTrainingFragment newInstance(int sectionNumber) {
BallTrainingFragment fragment = new BallTrainingFragment();
Bundle args = new Bundle();
args.putInt(Constants.ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create default options which will be used for every
// displayImage(...) call if no options will be passed to this method
DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
.cacheInMemory(true)
.cacheOnDisk(true)
.build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getActivity().getApplicationContext())
.defaultDisplayImageOptions(defaultOptions)
.build();
ImageLoader.getInstance().init(config); // Do it on Application start
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
mRootView = inflater.inflate(R.layout.fragment_balltraining, container, false);
mRecyclerView = (RecyclerView) mRootView.findViewById(R.id.balltraining_list);
mRecyclerView.setHasFixedSize(true);
// Display under one column
mGridLayoutManager = new GridLayoutManager(getActivity(), 2);
mRecyclerView.setLayoutManager(mGridLayoutManager);
// Set orientation
mGridLayoutManager.setOrientation(GridLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(mGridLayoutManager);
return mRootView;
}
#Override
public void onStart() {
super.onStart();
new FetchBallTask().execute(URL_TO_HIT);
}
public class FetchBallTask extends AsyncTask<String, String, List<BallTrainingModel>> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected List<BallTrainingModel> doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuilder buffer = new StringBuilder();
String line ="";
while ((line = reader.readLine()) != null){
buffer.append(line);
}
String finalJson = buffer.toString();
JSONObject parentObject = new JSONObject(finalJson);
JSONArray parentArray = parentObject.optJSONArray("BasketballTraining");
List<BallTrainingModel> ballTrainingModelList = new ArrayList<>();
Gson gson = new Gson();
for(int i=0; i<parentArray.length(); i++) {
JSONObject finalObject = parentArray.getJSONObject(i);
/**
* below single line of code from Gson saves you from writing the json parsing yourself which is commented below
*/
BallTrainingModel ballTrainingModel = gson.fromJson(finalObject.toString(), BallTrainingModel.class);
ballTrainingModel.setCategory(finalObject.getString("category"));
ballTrainingModel.setThumbnail(finalObject.getString("thumb"));
List<BallTrainingModel.Cast> castList = new ArrayList<>();
for(int j=0; j<finalObject.getJSONArray("cast").length(); j++){
BallTrainingModel.Cast cast = new BallTrainingModel.Cast();
cast.setName(finalObject.getJSONArray("cast").getJSONObject(j).getString("name"));
castList.add(cast);
}
ballTrainingModel.setCastList(castList);
// adding the final object in the list
ballTrainingModelList.add(ballTrainingModel);
}
return ballTrainingModelList;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if(connection != null) {
connection.disconnect();
}
try {
if(reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(final List<BallTrainingModel> result) {
super.onPostExecute(result);
if(result != null) {
adapter = new BallTrainingAdapter(getActivity().getApplicationContext(), R.layout.fragment_balltraining_content, result);
mRecyclerView.setAdapter(adapter);
mRecyclerView.setOnClickListener(new AdapterView.OnClickListener() {
#Override
public void onClick(View v) {
int position = mRecyclerView.indexOfChild(v);
BallTrainingModel ballTrainingModel = result.get(position);
Intent intent = new Intent(getActivity(), BallTrainingDetailsActivity.class);
intent.putExtra("ballTrainingModel", new Gson().toJson(ballTrainingModel));
getActivity().startActivity(intent);
}
});
} else {
Toast.makeText(getActivity().getApplicationContext(), "Not able to fetch data from server, please check url.", Toast.LENGTH_SHORT).show();
}
}
}
public class BallTrainingAdapter extends RecyclerView.Adapter<CustomViewHolder> {
private List<BallTrainingModel> ballTrainingList;
private int resource;
private LayoutInflater inflater;
public BallTrainingAdapter(Context context,int resource, List<BallTrainingModel> objects) {
ballTrainingList = objects;
this.resource = resource;
inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup viewGroup, int position) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.fragment_balltraining_content, null);
CustomViewHolder viewHolder = new CustomViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(CustomViewHolder customViewHolder, int position) {
BallTrainingModel ballTraining = ballTrainingList.get(position);
ImageLoader.getInstance().displayImage(ballTrainingList.get(position).getThumbnail(), customViewHolder.thumbnail);
//Setting text view title
customViewHolder.textView.setText(ballTrainingList.get(position).getCategory());
}
#Override
public int getItemCount() {
return (null != ballTrainingList ? ballTrainingList.size() : 0);
}
}
public class CustomViewHolder extends RecyclerView.ViewHolder{
protected TextView textView;
protected ImageView thumbnail;
public CustomViewHolder(View view) {
super(view);
this.textView = (TextView) view.findViewById(R.id.category);
this.thumbnail = (ImageView) view.findViewById(R.id.thumbnail);
}
}
}
I think that not clickable problem is on this line of code:
mRecyclerView.setOnClickListener(new AdapterView.OnClickListener() {
#Override
public void onClick(View v) {
And here is 2nd level fragment, which should render ListView and be clickable to 3rd level of details. Can someone give any example of how to make this?
public class BallTrainingDetailsActivity extends ActionBarActivity {
private TextView name;
private TextView tvCast;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_balltraining_list);
// Showing and Enabling clicks on the Home/Up button
if(getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
// setting up text views and stuff
setUpUIViews();
// recovering data from MainActivity, sent via intent
Bundle bundle = getIntent().getExtras();
if(bundle != null){
String json = bundle.getString("ballTrainingModel");
BallTrainingModel ballTrainingModel = new Gson().fromJson(json, BallTrainingModel.class);
StringBuffer stringBuffer = new StringBuffer();
for(BallTrainingModel.Cast cast : ballTrainingModel.getCastList()){
stringBuffer.append(cast.getName() + ", ");
}
tvCast.setText(stringBuffer);
//tvStory.setText(movieModel.getStory());
}
}
private void setUpUIViews() {
name = (TextView)findViewById(R.id.Name);
}
}
Here is JSON file:
{
"BasketballTraining": [
{
"thumb":"https://kycapitalliving.files.wordpress.com/2014/02/basketball-thumbnail.jpg",
"category": "Ball Handling",
"cast": [
{
"name": "Robert Downey Jr."
},
{
"name": "Chris Evans"
},
{
"name": "Mark Ruffalo"
}
]
},
{
"thumb":"https://kycapitalliving.files.wordpress.com/2014/02/basketball-thumbnail.jpg",
"category": "Shooting",
"cast": [
{
"name": "Matthew McConaughey"
},
{
"name": "Anne Hathaway"
},
{
"name": "Jessica Chastain"
},
{
"name": "Wes Bentley"
}
]
},
{
"thumb":"https://kycapitalliving.files.wordpress.com/2014/02/basketball-thumbnail.jpg",
"category": "Post Moves",
"cast": [
{
"name": "Miles Teller"
},
{
"name": "Kate Mara"
},
{
"name": "Michael B. Jordan"
}
]
},
{
"thumb":"https://kycapitalliving.files.wordpress.com/2014/02/basketball-thumbnail.jpg",
"category": "Defense",
"cast": [
{
"name": "Christian Bale"
},
{
"name": "Heath Ledger"
},
{
"name": "Aaron Eckhart"
}
]
},
{
"thumb":"https://kycapitalliving.files.wordpress.com/2014/02/basketball-thumbnail.jpg",
"category": "Scoring",
"cast": [
{
"name": "Viggo Mortensen"
},
{
"name": "Ian McKellen"
},
{
"name": "Elijah Wood"
}
]
},
{
"thumb":"https://kycapitalliving.files.wordpress.com/2014/02/basketball-thumbnail.jpg",
"category": "Others",
"cast": [
{
"name": "Roberto Benigni"
},
{
"name": "Nicoletta Braschi"
},
{
"name": "Giorgio Cantarini"
}
]
}
]
}
and here is my model:
public class BallTrainingModel {
private String thumbnail;
private String category;
#SerializedName("cast")
private List<Cast> castList;
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public List<Cast> getCastList() {
return castList;
}
public String getThumbnail() {
return thumbnail;
}
public void setThumbnail(String thumbnail) {
this.thumbnail = thumbnail;
}
public void setCastList(List<Cast> castList) {
this.castList = castList;
}
public static class Cast {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
Any examples or help would appreciated. Thank you in advance.
In RecyclerView Adapter there is a method onBindView
you have to apply there setOnClickListener :
For example :
#Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
holder.mCardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Your Code
});
}
}
For ref : check this link

Categories

Resources