Android Recycle View inside fragment show "No adapter attached; skipping layout " - android

if i write this code in a class extends AppCompatActivity it
works but in a fragment class i don't know why it doesn't work .
in the activity that has this fragment i use another adapter
to show products with the same code and it works
public class Categroy extends Fragment{
// CONNECTION_TIMEOUT and READ_TIMEOUT are in milliseconds
public static final int CONNECTION_TIMEOUT = 10000;
public static final int READ_TIMEOUT = 15000;
public RecyclerView mRVcategoryList;
public AdapterCategory mAdapter;
private String myurl="http://10.0.3.2/mobilaApp/category.php";
// private String categoryurl="http://10.0.3.2/mobilaApp/category.php";
public LinearLayoutManager layoutManager;
List<DataCategory> data=new ArrayList<>();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// execute asyncLogin
new AsyncLogin().execute();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_categroy, container, false);
RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.rvcat);
// 2. set layoutManger
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
// 3. create an adapter
AdapterCategory mAdapter = new AdapterCategory(getActivity().getApplicationContext(), data);
// 4. set adapter
recyclerView.setAdapter(mAdapter);
recyclerView.setItemAnimator(new DefaultItemAnimator());
return rootView;
}
private class AsyncLogin extends AsyncTask<String, String, String> {
ProgressDialog pdLoading = new ProgressDialog(getActivity());
HttpURLConnection conn;
URL url = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
//this method will be running on UI thread
pdLoading.setMessage("\tLoading...");
pdLoading.setCancelable(false);
pdLoading.show();
}
#Override
protected String doInBackground(String... params) {
try {
// Enter URL address where your json file resides
// Even you can make call to php file which returns json data
url = new URL(myurl);
// urlcat = new URL(categoryurl);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return e.toString();
}
try {
// Setup HttpURLConnection class to send and receive data from php and mysql
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(READ_TIMEOUT);
conn.setConnectTimeout(CONNECTION_TIMEOUT);
conn.setRequestMethod("GET");
// setDoOutput to true as we recieve data from json file
conn.setDoOutput(true);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return e1.toString();
}
try {
int response_code = conn.getResponseCode();
// Check if successful connection made
if (response_code == HttpURLConnection.HTTP_OK) {
// Read data sent from server
InputStream input = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
// Pass data to onPostExecute method
return (result.toString());
} else {
return ("unsuccessful");
}
} catch (IOException e) {
e.printStackTrace();
return e.toString();
} finally {
conn.disconnect();
}
}
#Override
protected void onPostExecute(String result) {
//this method will be running on UI thread
// dississ dialog pdLoading.dismiss();
pdLoading.dismiss();
try {
JSONArray jArray = new JSONArray(result);
// Extract data from json and store into ArrayList as class objects
for(int i=0;i<jArray.length();i++){
JSONObject json_data = jArray.getJSONObject(i);
DataCategory categorydata = new DataCategory();
categorydata.name_cat= json_data.getString("name_cat");
data.add(categorydata);
}
mRVcategoryList = (RecyclerView)getActivity(). findViewById(R.id.rvcat);
mAdapter = new AdapterCategory(getActivity().getApplicationContext(), data);
mRVcategoryList.setAdapter(mAdapter);
mRVcategoryList.setLayoutManager(new LinearLayoutManager(getActivity().getApplicationContext()));
} catch (JSONException e) {
Toast.makeText(getActivity().getApplicationContext(), e.toString(), Toast.LENGTH_LONG).show();
}
}
}
}
/* if i write this code in a class extends AppCompatActivity it
works but in a fragment class i don't know why it doesn't work .
in the activity that has this fragment i use another adapter
to show products with the same code and it works
*/
Adapter is here
public AdapterCategory(Context context, List<DataCategory> data){
this.context=context;
inflater= LayoutInflater.from(context);
this.data=data;
}
// Inflate the layout when viewholder created
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view=inflater.inflate(R.layout.categoryrow, parent,false);
MyHolder holder=new MyHolder(view);
return holder;
}
// Bind data
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
// Get current position of item in recyclerview to bind data and assign values from list
MyHolder myHolder= (MyHolder) holder;
DataCategory current=data.get(position);
myHolder.namecat.setText(current.name_cat);
}
// return total item from List
#Override
public int getItemCount() {
return data.size();
}
class MyHolder extends RecyclerView.ViewHolder{
TextView namecat;
// TextView textPrice;
// create constructor to get widget reference
public MyHolder(View itemView) {
super(itemView);
namecat= (TextView) itemView.findViewById(R.id.category_name);
}
}
}

Set layoutManager to your recyclerView using getContext() instead of getActivity() and it will work.
mListLayoutManager=new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(mListLayoutManager);

Thank you all
the problem was to replace getActivity() by getView() onpostexecute
mRVFishPrice = (RecyclerView)getView().findViewById(R.id.fishPriceList);
mAdapter = new AdapterFish(getActivity(), data);
mRVFishPrice.setAdapter(mAdapter);
mRVFishPrice.setLayoutManager(new LinearLayoutManager(getActivity()));

Related

RecycleView not calling methods

I'm trying to fetch data from a JSON, but it doesn't seem to work. OnBindViewHolder is never called...
ADAPTER CODE:
public class AdapterRallye extends RecyclerView.Adapter<AdapterRallye.MyViewHolder> implements View.OnClickListener {
private Context context;
private View.OnClickListener listener;
private List<DataRallye> data;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView Rallye_Nom;
public ImageView Rallye_Foto;
public TextView Rallye_Provincia;
public TextView Rallye_DataI;
public TextView Rallye_Tipus;
// create constructor to get widget reference
public MyViewHolder(final View itemView) {
super(itemView);
Rallye_Nom = (TextView) itemView.findViewById(R.id.tv_nom);
Rallye_Foto = (ImageView) itemView.findViewById(R.id.iv_foto);
Rallye_Provincia = (TextView) itemView.findViewById(R.id.tv_provincia);
Rallye_DataI = (TextView) itemView.findViewById(R.id.tv_datai);
Rallye_Tipus = (TextView) itemView.findViewById(R.id.tv_tipus);
}
}
// create constructor to innitilize context and data sent from MainActivity
public AdapterRallye(List<DataRallye> dadesrally) {
this.data = dadesrally;
}
// Inflate the layout when viewholder created
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.container_rallye, parent, false);
view.setOnClickListener(this);
return new MyViewHolder(view);
}
// Bind data
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
// Get current position of item in recyclerview to bind data and assign values from list
DataRallye current = data.get(position);
holder.Rallye_Nom.setText(current.getRallyeNom());
holder.Rallye_Tipus.setText(current.getRallyeTipus());
holder.Rallye_DataI.setText(current.getRallyeDataI());
holder.Rallye_Provincia.setText(current.getRallyeProvincia());
holder.Rallye_Provincia.setTextColor(ContextCompat.getColor(context, R.color.colorAccent));
// load image into imageview using glide
Glide.with(context).load("http://rallyecat.esy.es/fotos/" + current.getRallyeFoto())
.placeholder(R.drawable.rallyecatlogo)
.error(R.drawable.rallyecatlogo)
.into(holder.Rallye_Foto);
}
public void setOnClickListener(View.OnClickListener listener) {
this.listener = listener;
}
#Override
public void onClick(View view) {
if (listener != null)
listener.onClick(view);
}
// return total item from List
#Override
public int getItemCount() {
return data.size();
}
}
FRAGMENT CODE:
public class FragmentRally extends Fragment {
public FragmentRally() {
// Required empty public constructor
}
private List<DataRallye> llistarallyes = new ArrayList<>();
private RecyclerView recyclerView;
private AdapterRallye mAdapter;
private Intent intent;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_fragment_rally, container, false);
recyclerView = (RecyclerView) rootView.findViewById(R.id.llistarallyes);
mAdapter = new AdapterRallye(llistarallyes);
recyclerView.setAdapter(mAdapter);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
new AsyncFetch().execute();
mAdapter.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
intent = new Intent(getActivity(), ActivitatDetalls.class);
intent.putExtra("nombarra", llistarallyes.get(recyclerView.getChildAdapterPosition(view)).getRallyeNom());
startActivity(intent);
}
});
return rootView;
}
// CONNECTION_TIMEOUT and READ_TIMEOUT are in milliseconds
public static final int CONNECTION_TIMEOUT = 10000;
public static final int READ_TIMEOUT = 15000;
private class AsyncFetch extends AsyncTask<String, String, String> {
ProgressDialog pdLoading = new ProgressDialog(getActivity());
HttpURLConnection conn;
URL url = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
//this method will be running on UI thread
pdLoading.setMessage("\tCarregant...");
pdLoading.setCancelable(false);
pdLoading.show();
}
#Override
protected String doInBackground(String... params) {
try {
// Enter URL address where your json file resides
// Even you can make call to php file which returns json llistarallyes
url = new URL("http://www.rallyecat.esy.es/Obtenir_events.php");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return e.toString();
}
try {
// Setup HttpURLConnection class to send and receive llistarallyes from php and mysql
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(READ_TIMEOUT);
conn.setConnectTimeout(CONNECTION_TIMEOUT);
conn.setRequestMethod("GET");
// setDoOutput to true as we recieve llistarallyes from json file
//conn.setDoOutput(true);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return e1.toString();
}
try {
int response_code = conn.getResponseCode();
// Check if successful connection made
if (response_code == HttpURLConnection.HTTP_OK) {
// Read llistarallyes sent from server
InputStream input = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line + "\n");
}
// Pass llistarallyes to onPostExecute method
return (result.toString());
} else {
Toast.makeText(getActivity(), "No hi ha connexió a internet.",
Toast.LENGTH_LONG).show();
return ("No hi ha connexió a internet.");
}
} catch (IOException e) {
e.printStackTrace();
return e.toString();
} finally {
conn.disconnect();
}
}
#Override
protected void onPostExecute(String result) {
//this method will be running on UI thread
pdLoading.dismiss();
try {
JSONArray jArray = new JSONArray(result);
// Extract llistarallyes from json and store into ArrayList as class objects
for (int i = 0; i < jArray.length(); i++) {
JSONObject json_data = jArray.getJSONObject(i);
DataRallye dadesrallye = new DataRallye();
dadesrallye.setRallyeNom(json_data.getString("nom"));
dadesrallye.setRallyeTipus(json_data.getString("tipus"));
dadesrallye.setRallyeDataI(json_data.getString("datai"));
dadesrallye.setRallyeProvincia(json_data.getString("provincia"));
dadesrallye.setRallyeFoto(json_data.getString("foto"));
llistarallyes.add(dadesrallye);
}
} catch (JSONException e) {
Toast.makeText(getActivity(), e.toString(), Toast.LENGTH_LONG).show();
}
}
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(LayoutInflater inflater, ViewGroup parent) {
super(inflater.inflate(R.layout.fragment_fragment_rally, parent, false));
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Context context = v.getContext();
Intent intent = new Intent(v.getContext(), ActivitatDetalls.class);
context.startActivity(intent);
}
});
}
}
}
I've seen other StackOverflow posts where the problem is already solved, but I've been trying alot of the solutions the user said, but none is working...
Thanks!
Try to call mAdapter.notifyDataSetChanged(); in onPostExecute() method.
You need to notify your adapter after you made changes.

Arraylist throwing Nullpointer exception in android versions below Marshmallow

I am trying to use RssReader using a feedparser library. It is working fine on android M & N but it crashes on versions L and below.
here is what i have done
ReadRss readRss = new ReadRss(this, recyclerView);
isNetworkAvailable();
if (isNetworkAvailable()) {
readRss.execute();
} else {
Toast.makeText(getBaseContext(), "Couldn't connect to Internet.", Toast.LENGTH_LONG).show();
}
ReadRss is as follows
class ReadRss extends AsyncTask<Void, Void, Void> {
Context context;
private ProgressDialog progressDialog;
private ArrayList<FeedItem> feedItems;
private RecyclerView recyclerView;
ReadRss(Context context, RecyclerView recyclerView) {
this.recyclerView = recyclerView;
this.context = context;
progressDialog = new ProgressDialog(context);
progressDialog.setMessage("Loading...");
}
#Override
protected void onPreExecute() {
progressDialog.show();
super.onPreExecute();
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
progressDialog.dismiss();
RssAdapter adapter = new RssAdapter(context, feedItems);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
recyclerView.addItemDecoration(new VerticalSpace(50));
recyclerView.setAdapter(adapter);
}
#Override
protected Void doInBackground(Void... params) {
ProcessXml(Getdata());
return null;
}
private void ProcessXml(Document data) {
try {
URL url = new URL("http:pockettanksnews.blogspot.com/feeds/posts/default");
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream feedStream = httpConnection.getInputStream();
FeedParser parser = FeedParserFactory.newParser();
System.out.println("success");
Feed feed = parser.parse(feedStream);
feedItems=new ArrayList<>();
for (Item i : feed.getItemList()) {
FeedItem item=new FeedItem();
System.out.println(i.getTitle());
item.setTitle(i.getTitle());
System.out.println(i.getLink());
item.setLink(i.getLink());
System.out.println(i.getPubDate());
item.setPubDate(i.getPubDate().toString());
item.setThumbnailUrl("https:1079638729.rsc.cdn77.org/androidgame_img/pocket_tanks/real/1_pocket_tanks.jpg");
item.setDescription(i.getDescription());
feedItems.add(item);
}
} else {
System.out.println("error");
}
}
catch (Exception except){
;
}
}
private Document Getdata() {
try {
String address = "http://pockettanksnews.blogspot.com/feeds/posts/default/-/pttipsyoutube/?alt=rss";
URL url = new URL(address);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
InputStream inputStream = connection.getInputStream();
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document xmlDoc = builder.parse(inputStream);
return xmlDoc;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
and my RssAdapter is as below
public class RssAdapter extends RecyclerView.Adapter<RssAdapter.MyViewHolder> {
ArrayList<FeedItem> feedItems=new ArrayList<FeedItem>();
Context context;
public RssAdapter(Context context, ArrayList<FeedItem> feedItems) {
this.feedItems = feedItems;
this.context = context;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.custum_row_news_item, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
FeedItem current = feedItems.get(position);
holder.Title.setText(current.getTitle());
holder.Description.loadDataWithBaseURL("", current.getDescription(), "text/html", "UTF-8", "");
holder.Date.setText(current.getPubDate());
}
#Override
public int getItemCount() {
return feedItems.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView Title, Date;
WebView Description;
ImageView Thumbnail;
CardView cardView;
public MyViewHolder(View itemView) {
super(itemView);
Title = (TextView) itemView.findViewById(R.id.title_text);
Description = (WebView) itemView.findViewById(R.id.description_text);
Description.getSettings().setJavaScriptEnabled(true);
Date = (TextView) itemView.findViewById(R.id.date_text);
Thumbnail = (ImageView) itemView.findViewById(R.id.thumb_img);
cardView = (CardView) itemView.findViewById(R.id.cardview);
}
}
The app crashes on getItemCount method. It shows Null Pointer Exception : Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference.
In case of error your feeds will become null. So change your code and handle it.
// Add null check here.
if(feedItems!= null) {
RssAdapter adapter = new RssAdapter(context, feedItems);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
recyclerView.addItemDecoration(new VerticalSpace(50));
recyclerView.setAdapter(adapter);
} else {
// Show some error
}
Another way to handle this null pointer is add null check inside Adapter.
public RssAdapter(Context context, ArrayList<FeedItem> feedItems) {
if(feedItems!= null) {
this.feedItems.addAll(feedItems);
}
this.context = context;
}
Then try to find out exception if any in getting data from server. I believe only Getdata() method is responsible for that.

Handling image button click inside a RecycleView item

I have a button inside CardView which represents item of RecycleView. I've managed to handle the click event inside the ViewHolder class but I need to call function on MainActivity, How can I implement that with below code?
My code as below
ShopItemRecyclerViewAdapter.java
public class ShopItemRecyclerViewAdapter extends RecyclerView.Adapter<ShopItemRecyclerViewAdapter.ListItemViewHolder> {
static ArrayList<ShopListItemModel> list;
LayoutInflater inflater;
public ShopItemRecyclerViewAdapter(ArrayList<ShopListItemModel> list, Context context){
inflater = LayoutInflater.from(context);
this.list = list;
}
public ListItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.list_item, parent , false);
ListItemViewHolder vh = new ListItemViewHolder(view);
return vh;
}
public void onBindViewHolder(ListItemViewHolder holder, int position) {
ShopListItemModel current = list.get(position);
holder.name.setText(current.getName());
holder.price.setText(String.valueOf(current.getPrice()));
}
public int getItemCount() {
return list.size();
}
public static class ListItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
CardView cv;
TextView name;
TextView price;
ImageButton btnDelete;
ListItemViewHolder(final View itemView) {
super(itemView);
cv = (CardView)itemView.findViewById(R.id.cvShopListItem);
name = (TextView)itemView.findViewById(R.id.name);
price = (TextView)itemView.findViewById(R.id.price);
btnDelete = (ImageButton)itemView.findViewById(R.id.btnDeleteItem);
itemView.setOnClickListener(this);
btnDelete.setOnClickListener(this);
}
#Override
public void onClick(View v) {
//here i can handle the click but i think i need to use it in the main activity
}
}
}
MainActivity.java (skipped irrelevent code)
public class ShopCartScreen extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
RecyclerView cartItems; //recycler to hold the cart list
ArrayList<ShopListItemModel> list = new ArrayList<ShopListItemModel>();
ShopItemRecyclerViewAdapter adapter;
GetShopingCartList getShopingCartList; ////instance of network operation class to retrieve shop cart items list from server data base
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.shop_carts_list);
cartItems = (RecyclerView) findViewById(R.id.newListItem);
cartItems.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(this);
llm.setOrientation(LinearLayoutManager.VERTICAL);
cartItems.setLayoutManager(llm)
}
public void bindData(int listNumber) {
getShopingCartList = new GetShopingCartList(this, list, adapter, cartItems, listNumber, totalPrice);
getShopingCartList.execute("link to query which returns json object");
}
}
GetShopingCartList.java for network operation
public class GetShopingCartList extends AsyncTask<String, String, ArrayList<ShopListItemModel>> {
private ArrayList<ShopListItemModel> shopCartItemList;
Context context;
RecyclerView items;
ShopItemRecyclerViewAdapter adapter;
int listNumber;
public GetShopingCartList(Context context, ArrayList<ShopListItemModel> shopCartItemList, ShopItemRecyclerViewAdapter adapter,
RecyclerView items ,int listNumber) {
this.context = context;
this.shopCartItemList = shopCartItemList;
this.adapter = adapter;
this.items = items;
this.listNumber = listNumber;
}
protected ArrayList<ShopListItemModel> doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
shopCartItemList = new ArrayList<ShopListItemModel>();
try {
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
String finalJson = buffer.toString();
JSONObject parentObject = new JSONObject(finalJson);
JSONArray parentArray = parentObject.getJSONArray("result");
for (int i = 0; i < parentArray.length(); i++) {
JSONObject finalObject = parentArray.getJSONObject(i);//get the cuttent json object which is representaion of shop cart model object
String name = finalObject.getString("name");
String price = finalObject.getString("price");
Double d = Double.parseDouble(price);
ShopListItemModel item = new ShopListItemModel(name, d);
shopCartItemList.add(item);//adds the shopcart to the list of shop carts model
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return shopCartItemList;
}
protected void onPostExecute(ArrayList<ShopListItemModel> s) {
super.onPostExecute(s);
adapter = new ShopItemRecyclerViewAdapter(shopCartItemList, context);
items.setAdapter(adapter);
}
public ArrayList<ShopListItemModel> getList() {
return shopCartItemList;
}
}
Implement a method inside ShopCartScreen.java, then you can use the context object inside the adapter.
((ShopCartScreen)context).methodImplemented(ShopListItemModel model)
//add this code inside onClick event of the button
ok this is my solution if anyone needs it (i combined 2 methods/ 1 in the main activity and 1 in the recycler adapter):
in my recycler adapter i added this delete method:
//delete the item from the recycler Immediately for user interaction
public void delete(int position){
list.remove(position);
notifyItemRemoved(position);
}
in my ViewHolder class:
ListItemViewHolder(final View itemView) {
super(itemView);
cv = (CardView)itemView.findViewById(R.id.cvShopListItem);
name = (TextView)itemView.findViewById(R.id.name);
price = (TextView)itemView.findViewById(R.id.price);
btnDelete = (ImageButton)itemView.findViewById(R.id.btnDeleteItem);
itemView.setOnClickListener(this);
btnDelete.setOnClickListener(this);
}
#Override
public void onClick(View v) {
((ShopCartScreen)context).deleteItem(getPosition());//calls method in main activity
delete(getPosition());
}
and in the main activity:
public void deleteItem(int postion){
list = getShopingCartList.getList();
ShopListItemModel tmp = list.get(postion);
tmp.getName(); //gets the item name to remove
shopCartModel.getNumber(); //gets the cart number for deleting the item for the correct cart
new DeleteCartItem(this , shopCartModel , tmp).execute(); //remove the item from the data base
}

ListItems doubles in number(duplicated) in Custom ListView in android

I am using a custom ListView which gets doubled in number(duplicate listItems) when I go to previous activity and again come to that ListViewActivity.
I can see where the problem occurs. When I go to the ListViewActivity for the first time everything is fine where the listitems are added to the ArrayList and the adapter is set. But when I go to the previous activity and come again to the ListViewActivity, the previously set listitems are still present in the Adapter and again the listitems are set when the process goes through setAdapter() which is causing the duplication of listitems.
I have came across many solutions like using notifyDataSetChanged(), clearing the ArrayList, setAdapter(null), etc. None of these solutions helped me.
I guess the solution is clearing the Adapterand the ArrayList and refreshing the Adapter. But I don't know how and where exactly to do it.
Here is my code:
This is the data recieving class in the LoadingActivity.java
private class CategoriesAsyncTask extends AsyncTask<String,Integer,Double>{
String res="";
String curState ="";
String httppoststr="";
boolean isNxtActivity=false;
#Override
protected Double doInBackground(String... params) {
// TODO Auto-generated method stub
postData(params[0]);
return null;
}
protected void onPostExecute(Double Result)
{
if(isNxtActivity)
{
Intent intent = new Intent(LoadingActivity.this, ListItemsActivity.class);
if(curState.equals(Constants.STATE_GET_STOCK_ITEMS))
{
intent.putStringArrayListExtra(Constants.STOCK_ITEMS_LIST, listOfItems);
intent.putExtra("curState", Constants.STATE_GET_STOCK_ITEMS);
intent.putExtra(Constants.CATEGORY_ID, categoryId);
intent.putExtra(Constants.CUSTOMER_ID, customerId);
LoadingActivity.this.startActivity(intent);
}
}
}
public void postData(String ValueIWantToSend) {
// Create a new HttpClient and Post Header
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(Constants.GatewayUrl);
try
{
JSONObject json = new JSONObject(ValueIWantToSend);
curState = json.getString("curState");
StringEntity se = new StringEntity(ValueIWantToSend);
httppost.setEntity(se);
httppost.setHeader("Accept", "application/json");
httppost.setHeader("Content-type", "application/json");
httppoststr =httppost.toString();
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
res = EntityUtils.toString(entity, "UTF-8");
JSONObject jsonobj = new JSONObject(res);
String state = jsonobj.getString(Constants.STATE);
if(Constants.RESPONSE_SUCCESS.equals(state.toLowerCase()))
{
isNxtActivity =true;
if(curState.equals(Constants.STATE_GET_STOCK_ITEMS))
{
JSONArray itemsListJsonArray=new JSONArray();
itemsListJsonArray=jsonobj.getJSONArray(Constants.STOCK_ITEMS_LIST);
for(int i=0;i<itemsListJsonArray.length();i++)
{
String itemslist=itemsListJsonArray.getString(i);
listOfItems.add(itemslist.toString());
}
}
}
}
catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
catch (JSONException e) {
e.printStackTrace();
}
}
}
ListViewActivity.java
private String[] arrayOfNames;
private String[] arrayOfImageUrls;
ArrayList<String> listOfNames = new ArrayList<String>();
ArrayList<String> listOfImageUrls = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_items);
itemsList=(ListView) findViewById(R.id.itemsList);
Bundle extras = getIntent().getExtras();
listOfItems = extras.getStringArrayList(Constants.STOCK_ITEMS_LIST); //The duplication occurs here while getting the data from the LoadingActivity when visiting this activity for the second time.
arrayOfNames = new String[listOfNames.size()];
for(int i=0;i<listOfNames.size();i++)
{
arrayOfNames[i]=listOfNames.get(i);
}
arrayOfImageUrls = new String[listOfImageUrls.size()];
for(int i=0;i<listOfImageUrls.size();i++)
{
arrayOfImageUrls[i]=listOfImageUrls.get(i);
}
listItemadapter = new CustomListItemsAdapter(this, arrayOfNames, arrayOfImageUrls);
itemsList.setAdapter(listItemadapter);
}
CustomAdapter.java
public class CustomListItemsAdapter extends BaseAdapter{
private Context context;
private LayoutInflater inflater;
private String[] arrayOfNames;
public CustomListItemsAdapter(ListItemsActivity listItemsActivity, String[] itemsName) {
// TODO Auto-generated constructor stub
context=listItemsActivity;
arrayOfNames = itemsName;
inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return arrayOfNames.length;
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public static class ViewHolder
{
private TextView itemName;
private ImageView itemImage;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView==null)
{
holder=new ViewHolder();
convertView = inflater.inflate(R.layout.list_item_content, parent, false);
holder.itemName = (TextView) convertView.findViewById(R.id.itemName);
holder.itemImage = (ImageView) convertView.findViewById(R.id.itemImage);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.itemName.setText(arrayOfNames[position]);
StrictMode.ThreadPolicy policy = new
StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
ListItemsAsyncTask listAsync = new ListItemsAsyncTask();
Drawable drawableIcon = listAsync.loadImageFromServer(arrayOfImageUrls[position]);
holder.itemImage.setImageDrawable(drawableIcon);
return convertView;
}
private class ListItemsAsyncTask extends AsyncTask<String, Integer, Double> {
String httpPostStr, res;
Boolean NextActivity = false;
public Drawable loadImageFromServer(String url)
{
try {
InputStream is = (InputStream) new URL(url).getContent();
Drawable drawable = Drawable.createFromStream(is, "src name");
return drawable;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
#Override
protected Double doInBackground(String... params) {
return null;
}
}
Any Suggestions???
UPDATE: I have found the problem behind this duplication. The second time when I come to the ListViewActivity the duplication occurs in the Bundle from which I get the data for the ListView and its contents.
Now I need a solution to stop the duplication in the Bundle. I have mentioned the duplication occuring line with a comment in ListViewActivity.java
Call the function setAdapter() only once in onCreate() , because onCreate() is called only when the activity first starts , second time when you start the activity onCreate() is not called , but if you destroy the activity , then onCreate() will be called again , make sure you are not destroying the activity .
probably you are loading list in onResume and you are adding items to list attached to adapter and here you have duplicate each time.
Proper way is:
load data in onResume, make sure you are not adding duplicates to list, or clear list before adding data. then after fill list - check if adapter was initialised and attached if already initialised then add data to list and simple make on adapter .notifyDataSetChanged() if not initialised then initialise it with attaching your list to it.
Make attention when you attached list to adapter then you cannot change pointer to your list variable:
yourList = downloadedList; // Wrong way you will override the pointer to list in adapter
must be something like:
yourList.clear();
yourList.addAll(downloadedList); // Correct way
adapter.notifyDataSetChanged();

How to populate partial Data into ListView

Still i am populating all JSON data into ListView, but now i want to populate (records into ListView) based on visibility, when user scrolls I want to show progess bar for 5 seconds and then want to populate more records (those will be visible to user) and so on...
I don't want to populate all data into ListView for the first time !
MainActivity.java:
public class MainActivity extends Activity {
ArrayList<Main> arrayList;
MainAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
arrayList = new ArrayList<Main>();
new JSONAsyncTask().execute("....");
ListView listview = (ListView)findViewById(R.id.list);
adapter = new MainAdapter(getApplicationContext(), R.layout.row, arrayList);
listview.setAdapter(adapter);
listview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long id) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), arrayList.get(position).getTitle(), Toast.LENGTH_LONG).show();
}
});
}
class JSONAsyncTask extends AsyncTask<String, Void, Boolean> {
ProgressDialog dialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(MainActivity.this);
dialog.setMessage("Loading, please wait");
dialog.show();
dialog.setCancelable(false);
}
#Override
protected Boolean doInBackground(String... urls) {
try {
//------------------>>
HttpGet httppost = new HttpGet(urls[0]);
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(httppost);
// StatusLine stat = response.getStatusLine();
int status = response.getStatusLine().getStatusCode();
if (status == 200) {
HttpEntity entity = response.getEntity();
String data = EntityUtils.toString(entity);
JSONObject jsono = new JSONObject(data);
JSONArray jarray = jsono.getJSONArray("data");
for (int i = 0; i < jarray.length(); i++) {
JSONObject object = jarray.getJSONObject(i);
Main main = new Main();
main.setTitle(object.getString("title"));
Log.v("title:", object.getString("title"));
arrayList.add(main);
}
return true;
}
//------------------>>
} catch (ParseException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return false;
}
protected void onPostExecute(Boolean result) {
dialog.cancel();
adapter.notifyDataSetChanged();
if(result == false)
Toast.makeText(getApplicationContext(), "Unable to fetch data from server", Toast.LENGTH_LONG).show();
}
}
}
MainAdapter.java:
public class MainAdapter extends BaseAdapter {
ArrayList<Main> arrayList;
LayoutInflater layoutInflater;
int resource;
ViewHolder viewHolder;
public MainAdapter(Context context, int resource, ArrayList<Main> arrayList) {
this.layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.resource = resource;
this.arrayList = arrayList;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return arrayList.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return arrayList.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// convert view = design
View view = convertView;
if (view == null) {
viewHolder = new ViewHolder();
view = layoutInflater.inflate(resource, null);
viewHolder.tvName = (TextView) view.findViewById(R.id.tvName);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.tvName.setText(arrayList.get(position).getTitle());
return view;
}
static class ViewHolder {
public TextView tvName;
}
}
You can try using this library (Android-Infinite-Scroll-Listview)
I've used it before and it's easy to work with.

Categories

Resources