BaseAdapter notifyDatasetChanged() called but getView() is never called - java

I have a custom adapter that visualize each row in the list of Orders.
public class OrderRowAdapter extends BaseAdapter implements OnClickListener {
OrderList items_;
LayoutInflater inflater_;
int list_view_resource_id_;
private final String TAG = "OrderRowAdapter";
public OrderRowAdapter(Context context, int list_view_resource_id,
OrderList items) {
this.list_view_resource_id_ = list_view_resource_id;
this.items_ = items;
this.inflater_ = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public Object getItem(int position) {
return items_.getOrders(position);
}
public View getView(int position, View convertView, ViewGroup parent) {
Log.d(TAG, "View updated for item in position = " + position);
View v = convertView;
if (v == null) {
v = inflater_.inflate(list_view_resource_id_, parent);
}
Order item = items_.getOrders(position);
if (item != null) {
TextView order_info_tv = (TextView) v.findViewById(R.id.order_info);
TextView order_status_tv = (TextView) v.findViewById(R.id.order_status);
if (order_info_tv != null) {
order_info_tv.setText(
String.format("For customer: %s\nTotal of %d items", item.getCustomerId(), item.getItemsCount()));
}
if (order_status_tv != null) {
order_status_tv.setText("Status: " + getStatusText(item.getStatus()));
}
}
return v;
}
public int getCount() {
if (items_ == null) {
Log.d(TAG, "Null so get count returned 0");
return 0;
} else {
Log.d(TAG, "Get count returned " + items_.getOrdersCount());
return items_.getOrdersCount();
}
};
After querying new list of orders from a web service, I want to update the content of the ListView, so I have my Activity does the updating before calling notifyDataSetChanged()
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.orders);
initThreading();
findViews();
setUrls();
// Load the list of order from disk
try {
order_list_ = OrderList.parseFrom(new FileInputStream(
"/sdcard/orderList.bin"));
} catch (FileNotFoundException e) {
Log.e(TAG, "Cannot find the file", e);
} catch (IOException e) {
Log.e(TAG, "Cannot read the file", e);
}
order_row_adapter_ = new OrderRowAdapter(OrderActivity.this,
R.layout.order_row, order_list_);
orders_listview_.setAdapter(order_row_adapter_);
// Request new updates from the server
updateOrderInformation(-1);
}
public void updateOrders(InputStream new_order_stream) {
Log.d(TAG, "Updating order UI");
try {
order_list_.parseFrom(new_order_stream);
} catch (IOException e) {
Log.e(TAG, "IOException" , e);
}
runOnUiThread(new Runnable() {
public void run() {
guiUpdateOrders();
}
});
}
private void guiUpdateOrders() {
order_row_adapter_.notifyDataSetChanged();
Log.d(TAG, "Dataset notified that it has changed. GUI update anytime now.");
}
But, the getView() method of OrderRowAdapter is never called. The ListView is never updated.

It turns out the problem with my getView() not being called is because it is not visible. My layout xml has the upper TextView with fill_parent for its height. Thus the entire view only has that single TextView visible.
Solution: check the graphical view of the layout in question to make sure the ListView is visible.

Make sure BaseAdapter methods
registerDataSetObserver(DataSetObserver observer)
unregisterDataSetObserver(DataSetObserver observer)
are not overridden.

To change the content of your ListView, you must keep using the same reference to the List. Here you're creating another list and assigning it to the items_ variable (which does not contain the list itself, it's just a place to store a reference to a List), but your View still has a reference to the old list.
Instead of items_ = new_order_list this should work :
items_.clear();
items_.addAll(new_order_list);
EDIT :
To explain it better, try to create a new variable named old_items :
public void setNewOrderList(List<Order> new_order_list)
{
Log.d(TAG, "New Order List available. Num items = " + new_order_list.size());
List<Order> old_items = items_; // store the reference to the old list
items_ = new_order_list;
Log.d(TAG, "items_.size() = " + items_.size());
Log.d(TAG, "old_items.size() = " + old_items.size()); // The old list still exists, and it's the one used by your ListView
notifyDataSetChanged();
}

If all above answers not working try with invalidateViews()
ListView.invalidateViews() is used to tell the ListView to invalidate all its child item views (redraw them).
Note that there not need to be an equal number of views than items. That's because a ListView recycles its item views and moves them around the screen in a smart way while you scroll.
listView.invalidateViews()
My sample implementation,
lvitems.post(new Runnable() {
#Override
public void run() {
lvitems.invalidateViews(); //invalidate old
CustomAdapter customAdapter=new CustomAdapter(context, names, images); // load new data
customAdapter.notifyDataSetChanged();// call notifydatasetChanged
}
});
If any mistake in this answer please correct my mistakes.

Related

How to modify View-pager on Real time basis

I, am new to android. and I created one view pager which fetching image from firebase. and It's working fine. but there are some loopholes in that view pager which I failed to solve.
1) My View-pager not getting update on real-time basis. Means when ever I modify image in firebase. it's does't effect on real-time basis. I have to close my app and then have to start it again for seeing those updates.
2) When I am removing item from my list in firebase. My app getting crashed and in Logcat this exception is thrown.
java.lang.IndexOutOfBoundsException: Index: -1, Size: 5
at java.util.ArrayList.add(ArrayList.java:483)
at com.release.pack.lootbox.Fragments.HomeFragment$7.onEvent(HomeFragment.java:294)
at com.release.pack.lootbox.Fragments.HomeFragment$7.onEvent(HomeFragment.java:281)
Here is my code:
Slider Image Adapter:
public class SliderImageAdapter extends SliderViewAdapter<SliderImageAdapter.SliderAdapterVH> {
public List<Banner> bannerList;
public Context context;
public SliderImageAdapter(Context context, List<Banner> bannerList) {
this.bannerList = bannerList;
this.context = context;
}
#Override
public SliderAdapterVH onCreateViewHolder(ViewGroup parent) {
View inflate = LayoutInflater.from(parent.getContext()).inflate(R.layout.image_slider_myshop, parent, false);
return new SliderAdapterVH(inflate);
}
#Override
public void onBindViewHolder(final SliderAdapterVH viewHolder, final int position) {
Glide.with(viewHolder.itemView)
.load(bannerList.get(position).getmSliderImage())
.fitCenter()
.into(viewHolder.imageViewBackground);
}
#Override
public int getCount() {
return bannerList.size();
}
class SliderAdapterVH extends SliderViewAdapter.ViewHolder {
View itemView;
ImageView imageViewBackground;
ImageView imageGifContainer;
TextView textViewDescription;
public ProgressBar progressBar;
public ImageView imageViewFailed;
public SliderAdapterVH(View itemView) {
super(itemView);
imageViewBackground = itemView.findViewById(R.id.iv_auto_image_slider);
imageGifContainer = itemView.findViewById(R.id.iv_gif_container);
textViewDescription = itemView.findViewById(R.id.tv_auto_image_slider);
progressBar = itemView.findViewById(R.id.featured_deal_progress);
imageViewFailed = itemView.findViewById(R.id.featured_deal_img_failed_to_load);
this.itemView = itemView;
}
}
}
Home Fragment :
private SliderImageAdapter sliderImageAdapter;
private List<Banner> bannerList;
bannerList = new ArrayList<>();
sliderImageAdapter = new SliderImageAdapter(getActivity(),bannerList);
sliderMyshop = view.findViewById(R.id.imageSlider);
sliderMyshop.setSliderAdapter(sliderImageAdapter);
sliderMyshop.setIndicatorAnimation(IndicatorAnimations.WORM); //set indicator animation by using SliderLayout.IndicatorAnimations. :WORM or THIN_WORM or COLOR or DROP or FILL or NONE or SCALE or SCALE_DOWN or SLIDE and SWAP!!
sliderMyshop.setSliderTransformAnimation(SliderAnimations.SIMPLETRANSFORMATION);
sliderMyshop.setIndicatorSelectedColor(Color.WHITE);
sliderMyshop.setIndicatorUnselectedColor(Color.GRAY);
sliderMyshop.startAutoCycle();
mFirestore.collection("Banner").orderBy("priority", Query.Direction.DESCENDING).addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#javax.annotation.Nullable QuerySnapshot documentSnapshots, #javax.annotation.Nullable FirebaseFirestoreException e) {
if (e != null) {
Log.d(TAG, "Error : " + e.getMessage());
}
assert documentSnapshots != null;
for (DocumentChange doc : documentSnapshots.getDocumentChanges()) {
if (doc.getType() == DocumentChange.Type.ADDED) {
String doc_id = doc.getDocument().getId();
Banner banner = doc.getDocument().toObject(Banner.class).withDocId(doc_id);
bannerList.add(doc.getNewIndex(), banner);
sliderImageAdapter.notifyDataSetChanged();
} else if (doc.getType() == DocumentChange.Type.MODIFIED) {
String docID = doc.getDocument().getId();
Banner changedModel = doc.getDocument().toObject(Banner.class).withDocId(docID);
if (doc.getOldIndex() == doc.getNewIndex()) {
// Item changed but remained in same position
bannerList.set(doc.getOldIndex(), changedModel);
// sliderImageAdapter.notifyItemChanged(doc.getOldIndex());
} else {
// Item changed and changed position
bannerList.remove(doc.getOldIndex());
bannerList.add(doc.getNewIndex(), changedModel);
// sliderImageAdapter.notifyItemMoved(doc.getOldIndex(), doc.getNewIndex());
}
} else if (doc.getType() == DocumentChange.Type.REMOVED) {
// remove
bannerList.remove(doc.getOldIndex());
// sliderImageAdapter.notifyItemRemoved(doc.getOldIndex());
}
}
}
});
When I am adding a new image in firebase it's getting update on real-time basis. but not when I am doing modification in my image. or removing the item from my list.
Getting crashed
bannerList.add(doc.getNewIndex(), banner);
This line is the reason for the IndexOutOfBoundsException.
(java.lang.IndexOutOfBoundsException: Index: -1, Size: 5)
doc.getNewIndex() is returning -1. and list can not accept -1 as an index. so please check your doc.getNewIndex().
For realtime update
bannerList.clear();
add this code before your for loop, otherwise redundant data will be added and you can not update the new changes.
See this: The snapshot handler will receive a new query snapshot every time the query results change (that is, when a document is added, removed, or modified).
for every changes whole collection will be fetched

Best solution for Checkbox in LinearLayout

In my LinearLayout, there's a variable number of CheckBoxes. In a question I had a month ago someone said it´s better to add checkboxes dynamicly instead of make them not visible.
Integer[] count = new Integer[]{1,2,3,4,5,6,7,8,9,10};
size = mFrageList.get(position).getAuswahlList().size();
for (int i = 0; i < size; i++) {
cBox = new CheckBox(this);
cBox.setText(mFrageList.get(position).getAuswahlList().get(i));
cBox.setId(count[i]);
cBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
antwortencode[position] += "" + buttonView.getId();
frageBeantworten.setText("Antwort :"+antwortencode[position]+" abgeben");
} else {
String id = Integer.toString(buttonView.getId());
antwortencode[position] = antwortencode[position].replaceAll(id,"");
if(!antwortencode[position].isEmpty() || antwortencode[position]!= "") {
frageBeantworten.setText("Antwort :" + antwortencode[position] + " abgeben");
} else {
frageBeantworten.setText("Keine Checkbox(en) gewählt");
}
}
}
});
antworten.addView(cBox);
Currently, I'm able to save a string with the checked checkboxes, if I un-check a checkbox, it deletes it's value out of the string.
If I update the activity, the string is saved, and the checkboxes get a new List from the mFrageList.get(position)getAuswahlList(); and fill a new string in the "antwortencode" List with their values.
If I go back to the last position, I have the string which was generated but the checkboxes aren't checked anymore. But they have the Strings from the old position. that means everything is saved except the state of the checkboxes. I cant set a cBox.setChecked(isChecked) or buttonView.setChecked(isChecked) or buttonView.setChecked(buttonView.isChecked()) or something which is nearly the same in syntax.
I don't know what I can do besides declaring 10 Checkboxes in a xml file to talk to them one by one and set the VISIBLE.false if the auswahlList.get(position).isEmpty().
IMPORTANT: My XML is a Scrollable Activity because the size of the content overextended the screen. Thats why i didn´t and can´t use a Listview. So i need a solution that uses a LinearLayout
The truth is, you should actually use a ListView. As long as you reuse a layout multiple times - do it.
There are 2 options:
ListView as root - add other contents of your layout as different types of view
ListView inside a scrollable layout - there are many lightweight implementations of ListView that allow it to wrap content, e.g. https://github.com/paolorotolo/ExpandableHeightListView
The other thing is how to maintain the state of Checkboxes - use model classes. It's extremely easy with a ListView as it forces you to use an Adapter which provides methods to iterate over all positions.
Example of an adapter:
public class CheckableItemAdapter extends BaseAdapter {
private List<Pair<Integer, Boolean>> items = new ArrayList<>();
public void setItems(List<Pair<Integer, Boolean>> items) {
this.items = items;
}
#Override
public int getCount() {
return items.size();
}
#Override
public Object getItem(int position) {
return items.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
ViewHolder holder;
if (convertView == null) {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_checkable, parent, false);
holder = new ViewHolder(view);
view.setTag(holder);
} else {
view = convertView;
holder = (ViewHolder) view.getTag();
}
Pair<Integer, Boolean> item = items.get(position);
holder.itemCheck.setChecked(item.second);
return view;
}
static class ViewHolder {
CheckBox itemCheck;
public ViewHolder(View itemView) {
itemCheck = (CheckBox) itemView.findViewById(R.id.check);
}
}
}
I´ve managed to solve my problem alone, and now i want to share it, even if it isn´t the best example of programming.
Integer[] count = new Integer[]{1,2,3,4,5,6,7,8,9,10}; //maximum of 10 Checkboxes
size = mFrageList.get(position).getAuswahlList().size();
for (int i = 0; i < size; i++) {
cBox = new CheckBox(this);
cBox.setText(mFrageList.get(position).getAuswahlList().get(i));
cBox.setId(count[i]);
try{ //this is where the magic happens
if(antwortencode[position] != ""){ //cause i won´t want null in my db i´ve set "" as standard string in my activity for the List<String>
String code = antwortencode[position];
char[] c = code.toCharArray();
for(int j=0;j<=c.length;j++){
int x = c[j] -'0'; // 'char 1' - 'char 0' = Integer 1 , lol
if(cBox.getId()== x){ //compare them
cBox.toggle(); //if it fits, toggle
}
}
}
} catch (Exception e){
e.printStackTrace();
} //and here it ends
cBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
antwortencode[position] += "" + buttonView.getId();
frageBeantworten.setText("Antwort :"+antwortencode[position]+" abgeben");
} else {
String id = Integer.toString(buttonView.getId());
antwortencode[position] = antwortencode[position].replaceAll(id,"");
if(!antwortencode[position].isEmpty() || antwortencode[position]!= "") {
frageBeantworten.setText("Antwort :" + antwortencode[position] + " abgeben");
} else {
frageBeantworten.setText("Keine Checkbox(en) gewählt");
}
}
}
});
antworten.addView(cBox);
Ty for the answers and for the correction of my question.
Nostramärus

Android Error: IllegalStateException

I am working on a Bitcoin dashboard for Android. The following fragment uses the entered wallet address to display the balance in BTC. When an address is entered, it will add to the listview. When an item in the listview is selected, it will set the edittext to that address.
It is not yet complete, but for now it is throwing an error with the message, "The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread."
I currently have two example addresses in place for testing. If I select one then the other then the first again etc. it works fine. The error appears when I select one, press the button, then select the other.
public class WalletFragment extends Fragment {
ArrayList<String> savedWallets;
ArrayAdapter<String> listAdapter;
String newWalletAddress, jsonString, address, balance;
JSONObject jsonObj, data;
Double balanceDouble;
DecimalFormat df = new DecimalFormat("#.####");
private WalletListener listener;
public interface WalletListener {
void onCreateWallet(String newWalletAddress);
}
public WalletFragment() {
// Required empty public constructor
}
public static WalletFragment newInstance(ArrayList<String> wallets) {
WalletFragment fragment = new WalletFragment();
Bundle args = new Bundle();
args.putStringArrayList("savedWallets", wallets);
fragment.setArguments(args);
return fragment;
}
public static WalletFragment newInstance(ArrayList<String> wallets, String json) {
WalletFragment fragment = new WalletFragment();
Bundle args = new Bundle();
args.putStringArrayList("savedWallets", wallets);
args.putString("jsonString", json);
fragment.setArguments(args);
return fragment;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof WalletListener) {
listener = (WalletListener) context;
}
else {
throw new ClassCastException(context.toString()
+ " must implement MyListFragment.OnItemSelectedListener");
}
}
#Override
public void onDetach() {
super.onDetach();
listener = null;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_wallet, container, false);
ListView lv = (ListView) v.findViewById(R.id.walletListView);
df.setRoundingMode(RoundingMode.CEILING);
final EditText walletAddressEditText = (EditText) v.findViewById(R.id.walletAddressEditText);
TextView addressTV = (TextView) v.findViewById(R.id.walletAddresstextView);
TextView balanceTV = (TextView) v.findViewById(R.id.walletBalanceTextView);
savedWallets = getArguments().getStringArrayList("savedWallets");
if (savedWallets == null) {
savedWallets = new ArrayList<>();
}
savedWallets.add("198aMn6ZYAczwrE5NvNTUMyJ5qkfy4g3Hi");
savedWallets.add("1L8meqhMTRpxasdGt8DHSJfscxgHHzvPgk");
// TODO remove test addresses
jsonString = getArguments().getString("jsonString");
if (jsonString != null) {
try {
jsonString = getArguments().getString("jsonString");
jsonObj = new JSONObject(jsonString);
data = new JSONObject(jsonObj.getString("data"));
balance = data.getString("balance");
balanceDouble = Double.parseDouble(balance);
address = data.getString("address");
String walletAddressText = getResources().getString(R.string.wallet_address, address);
addressTV.setText(walletAddressText);
String walletBalanceText = getResources().getString(R.string.wallet_balance, df.format(balanceDouble));
balanceTV.setText(walletBalanceText);
// TODO add viewing for other wallet data at some point
} catch (Exception e) {
Log.d("TickerException", e.toString());
}
}
listAdapter = new ArrayAdapter<>(getActivity(), R.layout.main_list_rows, savedWallets);
lv.setAdapter(listAdapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
String address = savedWallets.get(position);
Log.d("wallet", "Selected: " + address);
walletAddressEditText.setText(address);
}
});
Button button = (Button) v.findViewById(R.id.createWalletButton);
View.OnClickListener ocl = new View.OnClickListener() {
#Override
public void onClick(View view) {
newWalletAddress = walletAddressEditText.getText().toString();
if (walletAddressEntryStructuralValidation(newWalletAddress)) {
if (newWalletAddress != null) {
listener.onCreateWallet(newWalletAddress);
}
else {
Toast.makeText(getActivity(), "newWalletAddress is null", Toast.LENGTH_SHORT).show();
}
}
else {
Toast.makeText(getActivity(), "Please enter a valid wallet address (length is currently " + newWalletAddress.length() + ").", Toast.LENGTH_SHORT).show();
}
}
};
// TODO check if wallet is already on list
button.setOnClickListener(ocl);
return v;
}
public boolean walletAddressEntryStructuralValidation(String address) {
return ((address.length() > 25) &&
(address.length() < 36) && (
(address.substring(0,1).equals("1") ||
(address.substring(0,1).equals("3")))));
}
// Wallet addresses are 26-35 alphanumeric characters and begin with 1 or 3
}
I believe this is all the relevant code but I will be closely watching this thread if anyone needs to request additional source.
That message means that the contents of the adapter (the order of items you see in getItem) changed but notifyDataSetChanged or similar function wasn't called. When changing the items in your adapter contents (which in this case is the savedWallets array list) you must call one of those functions.
Note: If you're adding several objects at once, you only need to call it once after all are added/removed. If you're mutating an object but not adding/removing it, you do not need to call it, but calling it may be the easiest way of doing a redraw.

How to make sure AsyncTask is executed

I'm pretty new to Android development, I feel like I have a relatively simple question here and have managed to tie down the more complex parts but overlook the more simple bits. I've setup an ImageAdapter class which handles displaying images into a GridView in another one of my Fragments. Originally I was following a tutorial that simply displayed a list of items in an Array.
I'm using an AsyncTask to populate an ArrayList, and then converting the ArrayList to a standard array that Picasso can deal with when displaying content.
My problem is that the AsyncTask section of my ImageAdapter is just not getting executed, thus my imageArr[] that Picasso uses is just remaining empty.
How can I make sure that the AsyncTask section of my Adapter is actually executed?
I've tried this, but it just doesn't seem to be working and I think I'm a little bit off...
public void onCreate() {
new GetProjects().execute();
}
I've attached my code bellow, any help would be really appreciated!
Note; ServiceHandler is just retrieving the data at the URL and then turning it into a string which can be parsed.
public class ImageAdapter extends BaseAdapter {
//JSON URL
private static String url = "www.myjsonsourceurl.com";
//JSON NODES
private static final String TAG_LOGO = "logopath";
ArrayList<String> imageUrls = new ArrayList<String>();
String[] imageArr = imageUrls.toArray(new String[imageUrls.size()]);
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return imageArr.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
public void onCreate() {
new GetProjects().execute();
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
// if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(185, 185));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(3, 3, 3, 3);
} else {
imageView = (ImageView) convertView;
}
Picasso.with(mContext).setIndicatorsEnabled(true);
Picasso.with(mContext).setLoggingEnabled(true);
Picasso.with(mContext).load(imageArr[position]).placeholder(R.drawable.ajaxloader).error(R.drawable.imageunavailable).into(imageView);
return imageView;
}
// references to our images
//ASYNC task to get json by making HTTP call
public class GetProjects extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Nothing right now
}
#Override
protected Void doInBackground(Void... arg0) {
// Creating service handler class instance
ServiceHandler sh = new ServiceHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url, ServiceHandler.GET);
Log.d("Response: ", "> " + jsonStr);
if (jsonStr != null) {
try {
JSONArray json = new JSONArray(jsonStr);
// looping through All Applications
for (int i = 0; i < json.length(); i++) {
JSONObject p = json.getJSONObject(i);
String logopath = p.getString(TAG_LOGO);
imageUrls.add(logopath);
}
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Log.e("ServiceHandler", "Couldn't get any data from the url");
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
}
You need to call in activity or fragment where list is defined not in adapter like this. move asynctask class to your activity and call it from there.
AsyncTask gives methods
onPreExecute() and onPostExecute() where you can toast message that task is started or completed. And you should call setAdapter() in onPostExecute() of class.
There`s no onCreate method for BaseAdapter which you can override. Execute your code
new GetProjects().execute();
either in contructor or call your onCreate function (I suggest changing its name) manualy from outside of the adapter.

Proper way to update ListView with data?

I am using ParseQueryAdapter like so:
public class MyPostedSalesAdapter extends ParseQueryAdapter<Sale> {
static String mTAG = "LocalSalesAdapter";
static ParseUser mCurrentUser = ParseUser.getCurrentUser();
public MyPostedSalesAdapter(Context context) {
super(context, new ParseQueryAdapter.QueryFactory<Sale>() {
#SuppressWarnings("unchecked")
public ParseQuery<Sale> create() {
#SuppressWarnings("rawtypes")
ParseQuery query = new ParseQuery("Sales");
query.orderByDescending("createdAt");
query.whereEqualTo("postedBy", mCurrentUser.getUsername());
try {
int salesAmount = query.count();
ProfileActivity.setTextView(salesAmount);
} catch (ParseException e) {
e.printStackTrace();
}
return query;
}
});
}
#Override
public View getItemView(Sale sale, View v, ViewGroup parent) {
if (v == null) {
v = View.inflate(getContext(), R.layout.listview_cell, null);
}
super.getItemView(sale, v, parent);
ParseImageView saleImage = (ParseImageView) v.findViewById(R.id.icon);
ParseFile photoFile = sale.getParseFile("photo");
if (photoFile != null) {
saleImage.setParseFile(photoFile);
saleImage.loadInBackground(new GetDataCallback() {
#Override
public void done(byte[] data, ParseException e) {
}
});
} else {
// Clear ParseImageView if the object has no photo, set placeholder.
saleImage.setImageResource(R.drawable.placeholder);
}
TextView titleTextView = (TextView) v.findViewById(R.id.textView_listView_saleTitle);
titleTextView.setText(sale.getSaleTitle());
TextView priceTextView = (TextView) v.findViewById(R.id.textView_listView_salePrice);
priceTextView.setText(sale.getSalePrice());
return v;
}
}
And simply onResume, setting the adapter to ListView like so:
#Override
protected void onResume() {
super.onResume();
mCurrentUser = ParseUser.getCurrentUser();
// Setting up currentUser to current logged in user
// If user is not logged in, present them with Login Activity
if (mCurrentUser == null || !isUserOnline())
{
presentUserWithLogin();
}
else
{
mOwnSalesAdapter = new MyPostedSalesAdapter(this);
mOwnSalesAdapter.loadObjects();
mUserSales.setAdapter(mOwnSalesAdapter);
}
}
I did this onResume, thinking every time the Activity is loaded, new data is pulled using query and displayed in the ListView. However this is not the case, and occasionally will act like this. Normally I have to close the entire app for the ListView to update properly and display any updates to the data. Even If I were to logout of the current parse user, and login on another account without closing the app, the previous user's posts sometimes appear as well in the listview. What am I doing wrong? I never encountered such problems with working in iOS. Also noticed if I were to delete an Item from Parse and go back, usually the item still appears in the ListView.
Hi just call in onResume()
if(mOwnSalesAdapter!=null)
mOwnSalesAdapter.notifyDataSetChanged();

Categories

Resources