There are two activities: Main and Detail Activity.
Main Activity is basically a GridView.
Detail Activity is basically shows the clicked item's detail information. I am passing selected item's id (pid) from the Main to the Detail Activity.
I am facing an issue as follows. Initially, I have 3G connection (cellular connection) and clicked on the first item and see the corresponding item detail in the Detail Activity, it works perfectly fine, and go back to the Main Activity, then clicked on the second item, then unfortunately it still shows me the first item in the DetailActivity that I clicked initially.
I switched from 3g to wifi while app is on the active and open. No matter what I click, it still shows me the first item that I clicked initially.
But when I delete the app and reinstall it and get either wifi access only, the app works perfectly fine.
In the following implementation, Connection URL (PRODUCT_DETAIL_URL) is http, not https. I am using Volley library for the network connection.
DetailActivity.java
private void productDetailInit() {
// it is http
StringRequest postRequest = new StringRequest(Request.Method.POST, Config.PRODUCT_DETAIL_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
jsonObject = response;
loadJsonData();
} catch (Exception e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
}
) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
params.put("id", productID);
return params;
}
};
RetryPolicy policy = new DefaultRetryPolicy(1000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
postRequest.setRetryPolicy(policy);
CustomVolleyRequest.getInstance(this).getRequestQueue().add(postRequest);
}
CustomVolleyRequest.java
public class CustomVolleyRequest {
private static CustomVolleyRequest customVolleyRequest;
private static Context context;
private RequestQueue requestQueue;
private ImageLoader imageLoader;
private CustomVolleyRequest(Context context) {
this.context = context;
this.requestQueue = getRequestQueue();
imageLoader = new ImageLoader(requestQueue,
new ImageLoader.ImageCache() {
private final LruCache<String, Bitmap>
cache = new LruCache<String, Bitmap>(20);
#Override
public Bitmap getBitmap(String url) {
return cache.get(url);
}
#Override
public void putBitmap(String url, Bitmap bitmap) {
cache.put(url, bitmap);
}
});
}
private class BitmapCache implements ImageLoader.ImageCache {
private LruCache<String, Bitmap> mCache;
public BitmapCache() {
mCache = new LruCache<>(20);
}
#Override
public Bitmap getBitmap(String url) {
return mCache.get(url);
}
#Override
public void putBitmap(String url, Bitmap bitmap) {
// scaling bitmap for avoiding too much big images
Bitmap scaled = ImageUtil.getInstance().scaleBitmap(bitmap);
mCache.put(url, scaled);
}
}
public static synchronized CustomVolleyRequest getInstance(Context context) {
if (customVolleyRequest == null) {
customVolleyRequest = new CustomVolleyRequest(context);
}
return customVolleyRequest;
}
public RequestQueue getRequestQueue() {
if (requestQueue == null) {
Cache cache = new DiskBasedCache(context.getCacheDir(), 10 * 1024 * 1024);
Network network = new BasicNetwork(new HurlStack());
requestQueue = new RequestQueue(cache, network);
requestQueue.start();
}
return requestQueue;
}
public ImageLoader getImageLoader() {
return imageLoader;
}
}
Adapter.java
class ProductMainAdapter extends ArrayAdapter<ImageRecord> {
private ImageLoader mImageLoader;
private String jsonObject;
ProductMainAdapter(Context context) {
super(context, R.layout.grid_item);
mImageLoader = CustomVolleyRequest.getInstance(this.getContext()).getImageLoader();
}
#NonNull
#Override
public View getView(final int position, View convertView, #NonNull ViewGroup parent) {
final ViewHolder holder;
if(convertView == null) {
holder = new ViewHolder();
convertView = LayoutInflater.from(getContext()).inflate(R.layout.grid_item, parent, false);
convertView.setBackgroundResource(R.drawable.round_gridview);
holder.priceTagImage = (ImageView) convertView.findViewById(R.id.priceTag_IV);
holder.textView = (TextView) convertView.findViewById(R.id.text);
holder.imageView = (NetworkImageView) convertView.findViewById(R.id.picture);
holder.priceTagRL = (RelativeLayout) convertView.findViewById(R.id.priceTag_RL);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
ImageRecord imageRecord = getItem(position);
holder.imageView.setImageUrl(imageRecord != null ? imageRecord.getUrl() : null, mImageLoader);
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
openProductDetail(position);
}
});
holder.textView.setText(imageRecord != null ? imageRecord.getTitle() : null);
holder.priceTagRL.setRotation(0);
return convertView;
}
private class ViewHolder{
TextView textView;
ImageView priceTagImage;
NetworkImageView imageView;
RelativeLayout priceTagRL;
}
private void openProductDetail(int position) {
try {
ImageRecord imr = getItem(position);
String productID = imr != null ? imr.getId() : "0";
Intent intent = new Intent(getContext(), ProductDetailActivity.class);
intent.putExtra("pid", productID);
getContext().startActivity(intent);
} catch (Exception e) {
Log.e("openProductDetail", "exception", e);
}
}
Related
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);
I apologize upfront if the question is too long. Here we go:
There are two activities: Main and Detail Activity.
Main Activity is basically a GridView.
Detail Activity is basically shows the clicked item's detail information. I am passing selected item's id (pid) from the Main to the Detail Activity.
I am facing an issue as follows. Initially, I have 3G connection (cellular connection) and clicked on the first item and see the corresponding item detail in the Detail Activity, it works perfectly fine, and go back to the Main Activity, then clicked on the second item, then unfortunately it still shows me the first item in the DetailActivity that I clicked initially.
I switched from 3g to wifi while app is on the active and open. No matter what I click, it still shows me the first item that I clicked initially.
But when I delete the app and reinstall it and get either wifi access only, the app works perfectly fine.
In the following implementation, Connection URL (PRODUCT_DETAIL_URL) is http, not https. I am using Volley library for the network connection.
DetailActivity.java
private void productDetailInit() {
// it is http
StringRequest postRequest = new StringRequest(Request.Method.POST, Config.PRODUCT_DETAIL_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
jsonObject = response;
loadJsonData();
} catch (Exception e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
}
) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
params.put("id", productID);
return params;
}
};
RetryPolicy policy = new DefaultRetryPolicy(1000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
postRequest.setRetryPolicy(policy);
CustomVolleyRequest.getInstance(this).getRequestQueue().add(postRequest);
}
CustomVolleyRequest.java
public class CustomVolleyRequest {
private static CustomVolleyRequest customVolleyRequest;
private static Context context;
private RequestQueue requestQueue;
private ImageLoader imageLoader;
private CustomVolleyRequest(Context context) {
this.context = context;
this.requestQueue = getRequestQueue();
imageLoader = new ImageLoader(requestQueue,
new ImageLoader.ImageCache() {
private final LruCache<String, Bitmap>
cache = new LruCache<String, Bitmap>(20);
#Override
public Bitmap getBitmap(String url) {
return cache.get(url);
}
#Override
public void putBitmap(String url, Bitmap bitmap) {
cache.put(url, bitmap);
}
});
}
private class BitmapCache implements ImageLoader.ImageCache {
private LruCache<String, Bitmap> mCache;
public BitmapCache() {
mCache = new LruCache<>(20);
}
#Override
public Bitmap getBitmap(String url) {
return mCache.get(url);
}
#Override
public void putBitmap(String url, Bitmap bitmap) {
// scaling bitmap for avoiding too much big images
Bitmap scaled = ImageUtil.getInstance().scaleBitmap(bitmap);
mCache.put(url, scaled);
}
}
public static synchronized CustomVolleyRequest getInstance(Context context) {
if (customVolleyRequest == null) {
customVolleyRequest = new CustomVolleyRequest(context);
}
return customVolleyRequest;
}
public RequestQueue getRequestQueue() {
if (requestQueue == null) {
Cache cache = new DiskBasedCache(context.getCacheDir(), 10 * 1024 * 1024);
Network network = new BasicNetwork(new HurlStack());
requestQueue = new RequestQueue(cache, network);
requestQueue.start();
}
return requestQueue;
}
public ImageLoader getImageLoader() {
return imageLoader;
}
}
Adapter.java
class ProductMainAdapter extends ArrayAdapter<ImageRecord> {
private ImageLoader mImageLoader;
private String jsonObject;
ProductMainAdapter(Context context) {
super(context, R.layout.grid_item);
mImageLoader = CustomVolleyRequest.getInstance(this.getContext()).getImageLoader();
}
#NonNull
#Override
public View getView(final int position, View convertView, #NonNull ViewGroup parent) {
final ViewHolder holder;
if(convertView == null) {
holder = new ViewHolder();
convertView = LayoutInflater.from(getContext()).inflate(R.layout.grid_item, parent, false);
convertView.setBackgroundResource(R.drawable.round_gridview);
holder.priceTagImage = (ImageView) convertView.findViewById(R.id.priceTag_IV);
holder.textView = (TextView) convertView.findViewById(R.id.text);
holder.imageView = (NetworkImageView) convertView.findViewById(R.id.picture);
holder.priceTagRL = (RelativeLayout) convertView.findViewById(R.id.priceTag_RL);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
ImageRecord imageRecord = getItem(position);
holder.imageView.setImageUrl(imageRecord != null ? imageRecord.getUrl() : null, mImageLoader);
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
openProductDetail(position);
}
});
holder.textView.setText(imageRecord != null ? imageRecord.getTitle() : null);
holder.priceTagRL.setRotation(0);
return convertView;
}
private class ViewHolder{
TextView textView;
ImageView priceTagImage;
NetworkImageView imageView;
RelativeLayout priceTagRL;
}
private void openProductDetail(int position) {
try {
ImageRecord imr = getItem(position);
String productID = imr != null ? imr.getId() : "0";
Intent intent = new Intent(getContext(), ProductDetailActivity.class);
intent.putExtra("pid", productID);
getContext().startActivity(intent);
} catch (Exception e) {
Log.e("openProductDetail", "exception", e);
}
}
I wonder what I am missing/ doing wrong in the provided implementation. It has been taking almost 2-3 months, I could not able to handle that issue. Has anyone ever faced a similar situation? Any suggestion or comment is highly appreciated.
You could just kill the activities with finish(); when the other one loads.
I was also having the same problem. In my case in onClick method the position was not correct.
Then I used to set the position as a tag to the specific view which has OnClickListener set and my problem solved.
It may be due to the position is declared as final. So remove the final keyword and try like this.
holder.imageView.setImageUrl(imageRecord != null ? imageRecord.getUrl() : null, mImageLoader);
holder.imageView.setTag(position);
holder.priceTagRL.setRotation(0);
And in onClick method
openProductDetail((int)view.getTag());
Check if the below link can be helpful:
https://stackoverflow.com/a/33682366/2798289 (3G connection might actually be slow that you to have increase the threshold of timeout)
Also, there is a chance the position reference in the adapter can come wrong in some edge case (irrespective of your actual issue). You can try the below alternative method..
Use gridView.setOnItemClickListener
gridview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
//do your logic based on the position
}
});
Note: In case if GridView is not able to observe the item click event, you have to set android:descendantFocusability="blocksDescendants" to the child root view under gridview. This might happen basically because the GridView items should not be clickable by itself as it will observe the click event.
Reference: https://developer.android.com/guide/topics/ui/layout/gridview.html
This question already has answers here:
Android. Fragment getActivity() sometimes returns null
(8 answers)
Closed 6 years ago.
this is my code:
public class LatestPostFragment extends Fragment {
private static final String TAG = LatestPostFragment.class.getSimpleName();
View rootView;
LinearLayout grid_view_wrapper;
private ViewPager viewPager;
private MyViewPagerAdapter myViewPagerAdapter;
private LinearLayout layout_dots;
private TextView[] dots;
private Integer viewPagerLength;
Typeface font;
ArrayList<Post>viewPagerItems = new ArrayList<Post>();
private List<Category> categoriesList;
public LatestPostFragment() {}
#Override
public void onResume() {
super.onResume();
//Get a Tracker (should auto-report)
if (Const.Analytics_ACTIVE) {
AnalyticsUtil.sendScreenName(getActivity(), TAG);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_latest, container, false);
//Forcing RTL Layout, If Supports and Enabled from Const file
Utils.forceRTLIfSupported(getActivity());
grid_view_wrapper = (LinearLayout) rootView.findViewById(R.id.grid_view_wrapper);
font = Typeface.createFromAsset(getActivity().getAssets(), "fonts/iran_sans.ttf");
ConnectionDetector cd = new ConnectionDetector(this.getActivity());
Boolean isInternetPresent = cd.isConnectingToInternet();
if (isInternetPresent) {
getFeaturedPosts();
categoriesList = AppController.getInstance().getPrefManger().getFeaturedCategories();
for (Category a : categoriesList) {
getLatestPosts(a.getId());
}
}
return rootView;
}
private void getFeaturedPosts(){
String featured_url = Const.URL_BLOG + Const.URL_BLOG_API + Const.URL_FEATURED + "?t=" + System.currentTimeMillis();
// making fresh volley request and getting json
JsonObjectRequest jsonReq = new JsonObjectRequest(Request.Method.GET, featured_url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
if (response != null) {
try {
if (response.has("error")) {
String error = response.getString("error");
Toast.makeText(getActivity().getApplicationContext(), error, Toast.LENGTH_LONG).show();
}else {
if (response.isNull("feed")) {
}else{
viewPagerLength = response.getInt("total_items");
JSONArray feedArray = response.getJSONArray("feed");
for (int i = 0; i < feedArray.length(); i++) {
JSONObject feedObj = (JSONObject) feedArray.get(i);
Post item = new Post();
item.setId(feedObj.getInt("id"));
item.setName(feedObj.getString("name"));
item.setCategory(feedObj.getString("category"));
String image = feedObj.isNull("image_big") ? null : feedObj.getString("image_big");
item.setImge(image);
item.setTimeStamp(feedObj.getString("timeStamp"));
item.setAuthor(feedObj.getString("author"));
// url might be null sometimes
String feedUrl = feedObj.isNull("url") ? null : feedObj.getString("url");
item.setUrl(feedUrl);
viewPagerItems.add(item);
}
setupViewPager();
}
}
}catch (JSONException es) {
es.printStackTrace();
Toast.makeText(getActivity().getApplicationContext(), "Featured: " + getString(R.string.unknown_error), Toast.LENGTH_LONG).show();
}
}else{
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
}
}) {
/** Passing some request headers **/
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json");
headers.put("ApiKey", Const.AuthenticationKey);
return headers;
}
};
// Adding request to volley request queue
AppController.getInstance().addToRequestQueue(jsonReq);
}
public void setupViewPager(){
layout_dots = (LinearLayout) rootView.findViewById(R.id.layout_dots);
viewPager = (ViewPager) rootView.findViewById(R.id.view_pager);
addBottomDots(0);
// viewpager change listener
ViewPager.OnPageChangeListener viewPagerPageChangeListener = new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
addBottomDots(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
};
myViewPagerAdapter = new MyViewPagerAdapter();
viewPager.setAdapter(myViewPagerAdapter);
viewPager.addOnPageChangeListener(viewPagerPageChangeListener);
}
private void addBottomDots(int currentPage) {
dots = new TextView[viewPagerLength];
layout_dots.removeAllViews();
for (int i = 0; i < Const.FeaturedView; i++) {
dots[i] = new TextView(getActivity());
dots[i].setText(Html.fromHtml("•"));
dots[i].setTextSize(35);
dots[i].setTextColor(getResources().getColor(R.color.viewpager_inactive));
layout_dots.addView(dots[i]);
}
if (dots.length > 0)
dots[currentPage].setTextColor(getResources().getColor(R.color.viewpager_active));
}
public class MyViewPagerAdapter extends PagerAdapter {
private LayoutInflater layoutInflater;
public MyViewPagerAdapter() {
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
layoutInflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(R.layout.viewpager_item, container, false);
final Post p = viewPagerItems.get(position);
TextView name = (TextView) view.findViewById(R.id.name);
name.setTypeface(font);
name.setTextSize(20);
name.setText(Html.fromHtml(p.getName()));
TextView category = (TextView) view.findViewById(R.id.category);
category.setText(Html.fromHtml(p.getCategory()));
ImageView img = (ImageView) view.findViewById(R.id.feedImage1);
Picasso.with(getActivity()).load(p.getImge()).into(img);
//TextView post_author = (TextView) view.findViewById(R.id.post_author);
//post_author.setText(String.format(getString(R.string.post_by), Html.fromHtml(p.getAuthor())));
CharSequence timeAgo = DateUtils.getRelativeTimeSpanString(
Long.parseLong(p.getTimeStamp()),
System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS);
TextView timestamp = (TextView) view.findViewById(R.id.timestamp);
// amin time
DateTime dateTime = new DateTime(Long.parseLong(p.getTimeStamp()));
dateTime.withZone(DateTimeZone.forID("Asia/Tehran"));
Roozh jCal = new Roozh();
jCal.GregorianToPersian(dateTime.getYear(), dateTime.getMonthOfYear(), dateTime.getDayOfMonth());
CharSequence timeAmin = jCal.toString();
// view time
if(System.currentTimeMillis() - Long.parseLong(p.getTimeStamp())<604800000)
timestamp.setText(String.format(getString(R.string.publish_on), timeAgo));
else
timestamp.setText(String.format(getString(R.string.publish_on), timeAmin));
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent();
i.setClass(getActivity(), PostViewActivity.class);
i.putExtra(PostViewActivity.TAG_SEL_POST_ID, "P" + p.getId());
i.putExtra(PostViewActivity.TAG_SEL_POST_TITLE, p.getName());
startActivity(i);
}
});
container.addView(view);
return view;
}
#Override
public int getCount() {
return viewPagerItems.size();
}
#Override
public boolean isViewFromObject(View view, Object obj) {
return view == obj;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
View view = (View) object;
container.removeView(view);
}
}
private void getLatestPosts(final String category_id){
String featured_url = Const.URL_BLOG + Const.URL_BLOG_API + Const.URL_FEATURED_CATEGORY_POST.replace("_CAT_ID_", category_id) + "?t=" + System.currentTimeMillis();
Log.d(TAG, featured_url);
// making fresh volley request and getting json
JsonObjectRequest jsonReq = new JsonObjectRequest(Request.Method.GET, featured_url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
if (response != null) {
try {
if (response.has("error")) {
String error = response.getString("error");
Toast.makeText(getActivity().getApplicationContext(), error, Toast.LENGTH_LONG).show();
}else {
if (response.isNull("feed")) {
}else{
LayoutInflater layoutInflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(R.layout.gridview_category, null, false);
final TextView category_button = (TextView) view.findViewById(R.id.btnCategory);
final String category_name = response.getString("category");
TextView category_title = (TextView) view.findViewById(R.id.category_title);
category_title.setText(Html.fromHtml(category_name));
category_title.setTypeface(font);
category_title.setTextSize(20);
category_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
((AppCompatActivity) getActivity()).getSupportActionBar().setSubtitle(category_name);
Fragment fragment = GridFragment.newInstance(GridFragment.PageType.CATEGORY, category_id, category_name);
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame_container, fragment).commit();
}
});
LinearLayout hsv = (LinearLayout) view.findViewById(R.id.recycler_view);
JSONArray feedArray = response.getJSONArray("feed");
for (int i = 0; i < feedArray.length(); i++) {
JSONObject feedObj = (JSONObject) feedArray.get(i);
View lvg = layoutInflater.inflate(R.layout.listview_item_grid, null, false);
TextView post_name = (TextView) lvg.findViewById(R.id.post_name);
post_name.setText(Html.fromHtml(feedObj.getString("name")));
ImageView img = (ImageView) lvg.findViewById(R.id.feedImage1);
Picasso.with(getActivity()).load(feedObj.getString("image_big")).into(img);
final Post item = new Post();
item.setId(feedObj.getInt("id"));
item.setName(feedObj.getString("name"));
/*item.setCategory(feedObj.getString("category"));
String image = feedObj.isNull("image_big") ? null : feedObj.getString("image_big");
item.setImge(image);
item.setTimeStamp(feedObj.getString("timeStamp"));
// url might be null sometimes
String feedUrl = feedObj.isNull("url") ? null : feedObj.getString("url");
item.setUrl(feedUrl);
postList.add(item);*/
lvg.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent();
i.setClass(getActivity(), PostViewActivity.class);
i.putExtra(PostViewActivity.TAG_SEL_POST_ID, "P" + item.getId());
i.putExtra(PostViewActivity.TAG_SEL_POST_TITLE, item.getName());
startActivity(i);
}
});
hsv.addView(lvg);
}
grid_view_wrapper.addView(view);
}
}
}catch (JSONException es) {
es.printStackTrace();
Toast.makeText(getActivity().getApplicationContext(), getString(R.string.unknown_error), Toast.LENGTH_LONG).show();
}
}else{
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
}
}) {
/** Passing some request headers **/
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json");
headers.put("ApiKey", Const.AuthenticationKey);
return headers;
}
};
// Adding request to volley request queue
AppController.getInstance().addToRequestQueue(jsonReq);
}
}
I have an error in this line:
LayoutInflater layoutInflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE)
Throwing this:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.app.Activity.getSystemService(java.lang.String)' on a null object reference
Well your getActivity() can return null if the context is lost after a long running background call like when running your jsonRequest.
Maybe the user clicks the home button while the request is running, and when it returns in the onResponse method, the activity is already destroyed, thus the getActivity() call returns a null object.
There are multiple solutions to this; easiest is a null check after the getActivity() return. Also you could check this stackoverflow question
I would suggest giving a Context to the PagerAdapter
public class MyViewPagerAdapter extends PagerAdapter {
private Context mContext;
public MyViewPagerAdapter(Context ctx) {
this.mContext = ctx;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.viewpager_item, container, false);
Now, you can use that class from any context, but from the Fragment, you do
myViewPagerAdapter = new MyViewPagerAdapter(getActivity());
Though, this may still be null for alternative reasons.
I am parsing a JSON array from a public source and inserting them into a custom ListView. I have 4 classes;
MySingleton for Volley Requests
public class MySingleton {
private static MySingleton mInstance;
private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
private static Context mCtx;
private MySingleton(Context context) {
mCtx = context;
mRequestQueue = getRequestQueue();
mImageLoader = new ImageLoader(mRequestQueue,
new ImageLoader.ImageCache() {
private final LruCache<String, Bitmap>
cache = new LruCache<String, Bitmap>(20);
#Override
public Bitmap getBitmap(String url) {
return cache.get(url);
}
#Override
public void putBitmap(String url, Bitmap bitmap) {
cache.put(url, bitmap);
}
});
}
public static synchronized MySingleton getInstance(Context context) {
if (mInstance == null) {
mInstance = new MySingleton(context);
}
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req) {
getRequestQueue().add(req);
}
public ImageLoader getImageLoader() {
return mImageLoader;
}}
GameListItem
public class GameListItem {
private String itemName, itemLongDescription, itemShortDescription, itemReleaseDate;
String releaseyear;
private int iconID, imageID;
public GameListItem(String itemName, String releaseyear, int iconID) {
this.itemName = itemName;
this.releaseyear = releaseyear;
this.iconID = iconID;
}
public String getItemName() {
return itemName;
}
public String getReleaseyear() {
return releaseyear;
}}
CustomListAdapter
public class CustomListAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater mInflater;
private List<GameListItem> mDataSource;
public CustomListAdapter(Context context, List<GameListItem> items) {
mContext = context;
mDataSource = items;
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return mDataSource.size();
}
#Override
public Object getItem(int position) {
return mDataSource.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = mInflater.inflate(R.layout.gamelist_layout, parent, false);
TextView titleTextView = (TextView) rowView.findViewById(R.id.gameTitle);
TextView subtitleTextView = (TextView) rowView.findViewById(R.id.gameDescription);
titleTextView.setText(mDataSource.get(position).getItemName());
subtitleTextView.setText(mDataSource.get(position).getReleaseyear());
return rowView;
}}
MainActivity
public class MainActivity extends AppCompatActivity {
final String TAG = this.getClass().getSimpleName();
RequestQueue requestQueue;
private CustomListAdapter adapter;
private List<GameListItem> gameList;
private GameListItem gameItem;
ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Cache cache = new DiskBasedCache(getCacheDir(), 1024*1024);
Network network = new BasicNetwork(new HurlStack());
requestQueue = new RequestQueue(cache, network);
requestQueue.start();
listView = (ListView) findViewById(R.id.gameListView);
gameList = new ArrayList<>();
//This works and gives me a ListView with 5 rows
gameList.add(new GameListItem("Test 1", "2019", R.mipmap.ic_launcher));
gameList.add(new GameListItem("Test 2", "2092", R.mipmap.ic_launcher));
gameList.add(new GameListItem("Test 3", "3243", R.mipmap.ic_launcher));
gameList.add(new GameListItem("Test 4", "2323", R.mipmap.ic_launcher));
gameList.add(new GameListItem("Test 5", "2123", R.mipmap.ic_launcher));
//This doesn't work...
String url = "http://api.androidhive.info/json/movies.json";
JsonArrayRequest stringRequest = new JsonArrayRequest(url, new Response
.Listener<JSONArray>(){
#Override
public void onResponse(JSONArray jsonArray) {
if (jsonArray == null) {
Toast.makeText(MainActivity.this, "jsonArray is Null", Toast.LENGTH_LONG).show();
} else {
try {
Toast.makeText(MainActivity.this, "ATTEMPTING PARSING", Toast.LENGTH_SHORT).show();
Log.e("This is the json array", jsonArray.toString());
for (int i = 0; i < jsonArray.length(); i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
String title = jsonObject.getString("title");
int releaseYear = jsonObject.getInt("releaseYear");
gameList.add(new GameListItem(releaseDate, "" + releaseYear , R.mipmap.ic_launcher));
//this prints all the Titles and Release Dates correctly
Log.e("This is a title", title);
Log.e("This is a year", "HERE " + releaseYear);
}
} catch(JSONException e){
Log.i("JSON exception", e.toString());
Toast.makeText(MainActivity.this, "JSON ERROR", Toast.LENGTH_LONG).show();
}
requestQueue.stop();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("This is an error", ""+error.getMessage()+","+error.toString());
}
});
MySingleton.getInstance(this).addToRequestQueue(stringRequest);
adapter = new CustomListAdapter(this, gameList);
listView.setAdapter(adapter);
}}
As commented in main activity, when i manually add a row (with manual data) the ListView builds and displays, but the parser isn't showing anything.
I checked countless of tutorials and everything seems in order, I even looked here and followed most of the answered I found yet nothing.
Can someone see the bug causing the list not to build/print?
PS. the Log.e prints as well (which is inside the parser)
Thank you!
If the request success, you must notify data change to adapter. In your case adapter.notifyDataSetChanged(); before catch block inside onResponse.
Add the following line after your requestQueue.stop statement:
adapter.notifyDataSetChanged();
At first, when you set the adapter, the list has no data, because the Volley request will be made asynchronously, that's why you need to let the adapter know when its data has changed.
From the documentation:
notifyDataSetChanged()
Notifies the attached observers that the underlying data has been changed and any View reflecting the data set should refresh itself.
I have a custom ListAdapter. I want to download image for every list item. I try to download them in AsyncTask (I found this solution in other discuss on so), but for some reason I always receive communicate "SkImageDecoder::Factory returned null"
public class MainMenuListAdapter extends BaseAdapter {
private List<Event> _events;
private Context _activityContext;
public MainMenuListAdapter(List<Event> events, Context context) {
this._events = events;
this._activityContext = context;
}
#Override
public int getCount() {
return this._events.size();
}
#Override
public Object getItem(int position) {
return this._events.get(position);
}
#Override
public long getItemId(int position) {
return this._events.get(position).getId();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView==null)
{
LayoutInflater inflater = (LayoutInflater) this._activityContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.mainmenu_list_item, parent,false);
}
Event e = (Event)getItem(position);
new DownloadImageTask((ImageView)convertView.findViewById(R.id.imageView1))
.execute("http://java.sogeti.nl/JavaBlog/wp-content/uploads/2009/04/android_icon_256.png");
TextView tvName = (TextView)convertView.findViewById(R.id.name);
tvName.setText(e.getName());
TextView tvDescription = (TextView)convertView.findViewById(R.id.description);
tvDescription.setText(e.getDescription());
TextView tvDate = (TextView)convertView.findViewById(R.id.date);
tvDate.setText(e.getDate());
TextView tvAddress = (TextView)convertView.findViewById(R.id.address);
tvName.setText(e.getAddress());
return convertView;
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
String uri = Uri.parse(urldisplay)
.buildUpon()
.appendQueryParameter("key", "val")
.build().toString();
Bitmap mIcon11 = null;
try {
URL url = new URL(uri);
InputStream in = url.openStream();
mIcon11 = BitmapFactory.decodeStream(in);
return mIcon11;
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
}