I dont know how to solve this problem
i cant find my error in codes
pls help me solve it :( thanks!
private void loadListFood() {
cart = new Database(this).getCarts();
adapter = new CartAdapter(cart,this);
recyclerView.setAdapter(adapter);
int total = 0;
for(Order order:cart)
total+=(Integer.parseInt(order.getPrice()))*(Integer.parseInt(order.getQuantity()));
Locale locale = new Locale("en", "US");
NumberFormat fmt = NumberFormat.getCurrencyInstance(locale);
txtTotalPrice.setText(fmt.format(total));
}
i am being redirected to
total+=(Integer.parseInt(order.getPrice()))*(Integer.parseInt(order.getQuantity()));
here is my adapter codes
public class CartAdapter extends RecyclerView.Adapter<CartViewHolder>{
private List<Order> listData = new ArrayList<>();
private Context context;
public CartAdapter(List<Order> cart, Cart cart1)
{
}
#Override
public CartViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View itemView = inflater.inflate(R.layout.cartlayout,parent,false);
return new CartViewHolder(itemView);
}
#Override
public void onBindViewHolder(CartViewHolder holder, int position) {
TextDrawable drawable = TextDrawable.builder()
.buildRound(""+listData.get(position).getQuantity(), Color.RED);
holder.img_cart_count.setImageDrawable(drawable);
int price = (Integer.parseInt(listData.get(position).getPrice()))*(Integer.parseInt(listData.get(position).getQuantity()));
holder.txt_price.setText(price);
holder.txt_cart_name.setText(listData.get(position).getProductName());
}
#Override
public int getItemCount() {
return listData.size();
}
}
From JavaDoc: The method Integer.parseInt(String s) throws a NumberFormatException
if the string does not contain a parsable integer.
That means, method order.getPrice() or order.getQuantity() returns "130 PHP" which is not a valid Integer.
Your real problem might be: Why the method returns a String and not Integer because you have to parse your String now. Pretty error prone and bad practice.
If your GUI element (or whatever) does not fit with Integer, at least remove your "PHP" out of the input field and you might be able to parse your String without manipulate it with some String helper methods.
class CartViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
, View.OnCreateContextMenuListener {
public TextView txt_cart_name,txt_price;
public ImageView img_cart_count;
private ItemClickListener itemClickListener;
public void setTxt_cart_name(TextView txt_cart_name) {
this.txt_cart_name = txt_cart_name;
}
public CartViewHolder(View itemView) {
super(itemView);
txt_cart_name = (TextView)itemView.findViewById(R.id.cart_item_name);
txt_price = (TextView)itemView.findViewById(R.id.cart_item_Price);
img_cart_count = (ImageView)itemView.findViewById(R.id.cart_item_count);
itemView.setOnCreateContextMenuListener(this);
}
#Override
public void onClick(View view) {
}
#Override
public void onCreateContextMenu(ContextMenu contextMenu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) {
contextMenu.setHeaderTitle("Selecione uma Ação");
contextMenu.add(0,0,getAdapterPosition(),Common.DELETE);
}
}
public class CartAdapter extends RecyclerView.Adapter<CartViewHolder> {
private List<Order> listData = new ArrayList<>();
private Context context;
public CartAdapter(List<Order> listData, Context context) {
this.listData = listData;
this.context = context;
}
#Override
public CartViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View itemView = inflater.inflate(R.layout.cart_layout,parent,false);
return new CartViewHolder(itemView);
}
#Override
public void onBindViewHolder(CartViewHolder holder, int position) {
TextDrawable drawable = TextDrawable.builder()
.buildRound(""+listData.get(position).getQuantity(), Color.BLUE);
holder.img_cart_count.setImageDrawable(drawable);
Locale locale = new Locale("pt","BR");
NumberFormat fmt = NumberFormat.getCurrencyInstance(locale);
int price = (Integer.parseInt(listData.get(position).getPrice()))*(Integer.parseInt(listData.get(position).getQuantity()));
holder.txt_price.setText(fmt.format(price));
holder.txt_cart_name.setText(listData.get(position).getProductName());
}
#Override
public int getItemCount() {
return listData.size();
}
}
Related
Basically i want to retrieve a int(score) generated from the current ListViewItem and assign it back to concrete TextView in my ListView.I am using SharedViewModel with LiveData but when i observe nothing happens.I am using Nav Architecture Component with Single activity.I'll be glad if someone helps.Thank u , here's some code.
public class ListFrag extends Fragment {
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
model.getCurrentScore().observe(getViewLifecycleOwner(), new Observer<Integer>() {
#Override
public void onChanged(#Nullable Integer s) {
for (int i = 0; i < myListView.getAdapter().getCount(); i++) {
v = myListView.getAdapter().getView(i,null, myListView);
finalScore = v.findViewById(R.id.finalScoreView);
if (s != null) {
itemAdapter = new ItemAdapter(getActivity(),items,bushido,description,s,finalScore);
myListView.setAdapter(itemAdapter);
finalScore.setText(String.valueOf(s));
}
((BaseAdapter)myListView.getAdapter()).notifyDataSetChanged();
}
}
});
}
public class SharedViewModel extends ViewModel
{
private MutableLiveData<Integer> currentScore = new MutableLiveData<>();
public LiveData<Integer> getCurrentScore(){
return currentScore;
}
public void setCurrentScore(Integer finito) {
currentScore.setValue(finito);
}
}
public class ItemAdapter extends BaseAdapter {
LayoutInflater mInflater;
String[] items;
String[] bushido;
String[] description;
TextView finalscorre;
Integer scr;
public ItemAdapter(Context c,String[] i ,String [] p ,String[] d, Integer scc,TextView sc) {
items = i;
bushido = p;
description = d;
finalscorre = sc;
scr = scc;
mInflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return items.length;
}
#Override
public Object getItem(int i) {
return items[i];
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View convertView, ViewGroup parent) {
View v = mInflater.inflate(R.layout.my_listview_detail, null);
TextView nameTextView = v.findViewById(R.id.NameTextView);
TextView bushidoTextView = v.findViewById(R.id.bushidoTextView);
TextView descriptionTextView = v.findViewById(R.id.descriptionTextView);
finalscorre = v.findViewById(R.id.finalScoreView);
String name = items[i];
String desc = description[i];
String bush = bushido[i];
finalscorre.setText("Waat");
nameTextView.setText(name);
descriptionTextView.setText(desc);
bushidoTextView.setText(bush);
ItemAdapter.this.notifyDataSetChanged();
return v;
}
}
When i try to assign the LiveData in TextView out of the ListView it works.But when i try this ,nothings happen (no errors and no result).
Adapters act as a bridge between the data (in your case, the string array you pass into the adapter), and the ListView (in your case, myListView). Any change to the ListView needs to be follow these steps:
make desired changes to the data itself
pass this new data to the adapter
adapter updates the list view
I have wrote some example code:
ItemAdapter
public class ItemAdapter extends BaseAdapter {
LayoutInflater mInflater;
String[] items;
String[] bushido;
String[] description;
// TextView finalscorre; // I commented out this TextView please see the comment below
Integer scr;
public ItemAdapter(Context c,String[] i ,String [] p ,String[] d, Integer scc,TextView sc) {
items = i;
bushido = p;
description = d;
// finalscorre = sc;
scr = scc;
mInflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void updateItems(String[] i, String[] p, String[] d, Integer scc) {
items = i;
bushido = p;
description = d;
scr = scc;
// notify the adapter to refresh the list view.
notifyDataSetChanged()
}
#Override
public int getCount() {
return items.length;
}
#Override
public Object getItem(int i) {
return items[i];
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View convertView, ViewGroup parent) {
View v = mInflater.inflate(R.layout.my_listview_detail, null);
TextView nameTextView = v.findViewById(R.id.NameTextView);
TextView bushidoTextView = v.findViewById(R.id.bushidoTextView);
TextView descriptionTextView = v.findViewById(R.id.descriptionTextView);
//finalscorre = v.findViewById(R.id.finalScoreView);
TextView finalscorre = v.findViewById(R.id.finalScoreView);
String name = items[i];
String desc = description[i];
String bush = bushido[i];
// finalscorre.setText("Waat");
finalscorre.setText(scr);
nameTextView.setText(name);
descriptionTextView.setText(desc);
bushidoTextView.setText(bush);
// ItemAdapter.this.notifyDataSetChanged(); Do NOT call this method inside getView
return v;
}
}
Fragment
public class ListFrag extends Fragment {
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Create and set adapter just once. Do not create or set new adapter in observer, for loop, etc.
itemAdapter = new ItemAdapter(getActivity(),items,bushido,description,s,finalScore);
myListView.setAdapter(itemAdapter);
model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
model.getCurrentScore().observe(getViewLifecycleOwner(), new Observer<Integer>() {
#Override
public void onChanged(#Nullable Integer s) {
itemAdapter.updateItems(items,bushido,description,s);
}
});
}
}
I wasn't able to figure out what finalscorre supposed to be so I assumed that this is the text view that stores the final score that you mentioned, and all list view items should have the same value. If this is not the case please clarify in your question.
Also note that while this solution is enough to solve the specific problem you mentioned, their are some other improvements that can be made:
Use RecyclerView instead of ListView.
Instead of maintaining multiple String[], define a POJO that represent the item, and have a single array.
Also, checking this adapter implementation in google sample will help.
inside adapter you are doing nothing that will update your LiveData
i'm facing a small issue figuring out on the following -
I have a RecyclerView in my MainActivity, the RecyclerView has CardView within it.
The data displays on the MinActivity page, cuz the RecyclerView is in it.
Now, I want a new activity to pop-up once a CardView is clicked.
The new activity will use the same data as the CardView had.
I'm using Firebase storage if it matters.
Example -
My CardView 1 has a name, age and country - Jake, 19, UK.
The other activity will get the collection data from Firebase which is the exact same as CardView 1 and implement it in to the new activity.
I hope I explained it well..
(I'm using getters and setters)
My code so far (Only the needed parts)-
MainActivity
list_post = new ArrayList<>();
list_header = new ArrayList<>();
postsAdapter = new PostsAdapter(list_post);
headerAdapter = new HeaderAdapter(list_header);
headerRecycler = (RecyclerView) findViewById(R.id.headerRecycler);
headerRecycler.setAdapter(headerAdapter);
headerRecycler.setLayoutManager(new LinearLayoutManager(this));
firebaseFirestore = FirebaseFirestore.getInstance();
firebaseFirestore.collection("FeaturedPosts").limit(1).addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(QuerySnapshot queryDocumentSnapshotss, FirebaseFirestoreException ee) {
for (DocumentChange doc2: queryDocumentSnapshotss.getDocumentChanges()) {
if (doc2.getType() == DocumentChange.Type.ADDED) {
ListForHeader listForHeader = doc2.getDocument().toObject(ListForHeader.class);
list_header.add(listForHeader);
headerAdapter.notifyDataSetChanged();
}
}
}
});
RecyclerAdapter
public class HeaderAdapter extends RecyclerView.Adapter<HeaderAdapter.ViewHolder2> {
public List<ListForHeader> list_header;
public Context contextt;
public HeaderAdapter (List<ListForHeader> list_header) {
this.list_header = list_header;
}
#NonNull
#Override
public HeaderAdapter.ViewHolder2 onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.featured_activity, parent, false);
contextt = parent.getContext();
return new HeaderAdapter.ViewHolder2(view);
}
#Override
public void onBindViewHolder(#NonNull HeaderAdapter.ViewHolder2 holder, int position) {
String header_data2 = list_header.get(position).getHeader2();
holder.setHeaderText2(header_data2);
String date_data2 = list_header.get(position).getDate2();
holder.setDateText2(date_data2);
String image_data2 = list_header.get(position).getImage_url2();
holder.setIntroIMG2(image_data2);
}
#Override
public int getItemCount() {
return list_header.size();
}
public class ViewHolder2 extends RecyclerView.ViewHolder {
private View mView;
private ImageView introIMG2;
private TextView headerText2;
private TextView dateText2;
public ViewHolder2(View itemView) {
super(itemView);
mView = itemView;
}
public void setHeaderText2(String headText2) {
headerText2 = mView.findViewById(R.id.introHeader2);
headerText2.setText(headText2);
}
public void setDateText2(String tarihText2) {
dateText2 = mView.findViewById(R.id.introDate2);
dateText2.setText(tarihText2);
}
public void setIntroIMG2 (String downloadUri) {
introIMG2 = (ImageView) mView.findViewById(R.id.introImage2);
Glide.with(contextt).load(downloadUri).into(introIMG2);
}
}
}
As far as I see its simple issue. You can add cardview Id to viewHolder and set onlclicklister to it in bindview and in on click Start activity and pass the current data in Intent. Let me know if its something else stopping you from sending data or getting click on cardview.
Extra: you may have to set cardview clickable true.
here is the example.
class DemoViewHolder extends RecyclerView.ViewHolder implements
View.OnClickListener {
#BindView(R.id.card)
CardView cardView;
public DemoViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
cardView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.card:
doSomethingOn(mList.get(getAdapterPosition()))
break;
}
}
public class BookingAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
Context mContext;
ArrayList<Booking> mList;
public BookingAdapter(Context context, ArrayList<Booking> list) {
mContext = context;
mList = list;
this.cancelBookingListener = cancelBookingListener;
}
Trying to implement a recycleview inside of a fragment using a custom adapter and receiving the following error.
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference. AtStoreAdapter.getItemCount(StoreAdapter.java:xx)
I have looked around SO, but have not seen anything that is leading to a solution. Any help would be appreciated.
Android app - Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
and a few others
StoreAdapter
public class StoreAdapter extends RecyclerView.Adapter<StoreAdapter.StoreHolder>{
private LayoutInflater mInflator;
private List<Store> mStore= Collections.emptyList();
private Context mContext;
public StoreAdapter(Context mContext, List<Store> mStore){
mInflator = LayoutInflater.from(mContext);
this.mStore = mStore;
this.mContext = mContext;
}
// Simple nested class that holds the various view components for the adapter
// and as specified in *layout.xml .
public class StoreHolder extends RecyclerView.ViewHolder{
TextView mStoreTitle, mStoreDetails, mStoreCategory;
public StoreHolder (View itemView){
super(itemView);
mStoreTitle = (TextView) itemView.findViewById(R.id.title);
mStoreDetails = (TextView) itemView.findViewById(R.id.details);
mStoreCategory = (TextView) itemView.findViewById(R.id.category);
}
}
// Called when the RecyclerView needs a new RecyclerView.ViewHolder (*Holder)
// to represent an item. We inflate the XML layout and return our view (*Holder)
#Override
public StoreHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflator.inflate(R.layout.todo_list_row, parent,false);
return new StoreHolder(view);
}
// Called by RecyclerView to display the data at the specified position.
// This method needs to update the contents of the view to reflect the item at the
// given position e.g. we are updating the view here with the data
#Override
public void onBindViewHolder(StoreAdapter.StoreHolder holder, int position) {
holder.mStoreTitle.setText(mStore.get(position).getStoreTitle());
holder.mStoreDetails.setText(mStore.get(position).getStoreDetails());
holder.mStoreCategory.setText(mStore.get(position).getStoreCategory());
}
public void setData(List<Store> store){
this.mStore = store;
}
public void delete(int position){
mStore.remove(position);
notifyItemRemoved(position);
}
#Override
public int getItemCount() {
return mStore.size();
}
}
StoreSectionLoader
public class StoreSectionLoader extends AsyncTaskLoader<List<Store>> {
private static final String LOG_TAG = StoreSectionLoader.class.getSimpleName();
private List<Store> mStore;
private ContentResolver mContentResolver;
private Cursor mCursor;
public StoreSectionLoader(Context context, Uri uri, ContentResolver contentResolver){
super(context);
mContentResolver = contentResolver;
}
#Override
public List<Store> loadInBackground() {
String[] projection = {BaseColumns._ID,
RetailFinderContract.RetailFinderColumns.STORE_COMPLETE,
RetailFinderContract.RetailFinderColumns.STORE_CREATED,
RetailFinderContract.RetailFinderColumns.STORE_TITLE,
RetailFinderContract.RetailFinderColumns.STORE_DETAILS,
RetailFinderContract.RetailFinderColumns.STORE_CATEGRORY};
List<Store> entry = new ArrayList<>();
Uri uri = RetailFinderContract.URI_LOCATION_TABLE;
mCursor = mContentResolver.query(uri, projection, null, null, null);
if(mCursor != null){
if(mCursor.moveToFirst()){
do {
int _id = mCursor.getInt(mCursor.getColumnIndex(BaseColumns._ID));
String store_title = mCursor.getString(
mCursor.getColumnIndex(RetailFinderContract.RetailFinderColumns.STORE_TITLE));
String store_details = mCursor.getString(
mCursor.getColumnIndex(RetailFinderContract.RetailFinderColumns.STORE_DETAILS));
String store_category = mCursor.getString(
mCursor.getColumnIndex(RetailFinderContract.RetailFinderColumns.STORE_CATEGRORY));
Store store = new Store(_id,store_title,store_details,store_category);
entry.add(store);
} while (mCursor.moveToNext());
}
}
return entry;
}
#Override
public void deliverResult(List<Store> store) {
if(isReset()){
if (mStore != null){
mCursor.close();
}
}
List<Store> oldStoreList = mStore;
if(mStore == null || mStore.size() == 0 ){
Log.d(LOG_TAG, "+++++++++++++++ No Data returned");
}
mStore = store;
if(isStarted()){
super.deliverResult(store);
}
if(oldStoreList != null && oldStoreList != store){
mCursor.close();
}
}
#Override
protected void onStartLoading() {
if(mStore != null){
deliverResult(mStore);
}
if(takeContentChanged() || mStore == null){
forceLoad();
}
}
#Override
protected void onStopLoading() {
cancelLoad();
}
#Override
protected void onReset() {
onStopLoading();
if(mCursor != null){
mCursor.close();
}
mStore = null;
}
#Override
public void onCanceled(List<Store> store) {
super.onCanceled(store);
if(mCursor != null){
mCursor.close();
}
}
#Override
public void forceLoad() {
super.forceLoad();
}
}
StoreFragment
public class StoreFragment extends Fragment implements
LoaderManager.LoaderCallbacks<List<Store>> {
private static final String LOG_TAG = StoreListFragment.class.getSimpleName();
private StoreAdapter mAdapter;
private static final int LOADER_ID = 1;
private ContentResolver mContentReslover;
private List<Store> mStore;
private Context mContext;
protected RecyclerView mRecyclerView;
private static final String TAG = "RecyclerViewFragment";
private static final String KEY_LAYOUT_MANAGER = "layoutManager";
private enum LayoutManagerType {
GRID_LAYOUT_MANAGER,
LINEAR_LAYOUT_MANAGER
}
protected LayoutManagerType mCurrentLayoutManagerType;
protected RecyclerView.LayoutManager mLayoutManager;
// end added
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
mContentReslover = getActivity().getContentResolver();
getLoaderManager().initLoader(LOADER_ID, null, this);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.store_list_row, container, false);
rootView.setTag(TAG);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.t_recycler);
mLayoutManager = new LinearLayoutManager(getActivity());
mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
if (savedInstanceState != null) {
// Restore saved layout manager type.
mCurrentLayoutManagerType = (LayoutManagerType) savedInstanceState
.getSerializable(KEY_LAYOUT_MANAGER);
}
setRecyclerViewLayoutManager(mCurrentLayoutManagerType);
mAdapter = StoreAdapter(getContext(), mStore); //issue
mRecyclerView.setAdapter(mAdapter);
return rootView;
}
public void setRecyclerViewLayoutManager(LayoutManagerType layoutManagerType) {
int scrollPosition = 0;
// If a layout manager has already been set, get current scroll position.
if (mRecyclerView.getLayoutManager() != null) {
scrollPosition = ((LinearLayoutManager) mRecyclerView.getLayoutManager())
.findFirstCompletelyVisibleItemPosition();
}
switch (layoutManagerType) {
case LINEAR_LAYOUT_MANAGER:
mLayoutManager = new LinearLayoutManager(getActivity());
mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
break;
default:
mLayoutManager = new LinearLayoutManager(getActivity());
mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
}
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.scrollToPosition(scrollPosition);
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save currently selected layout manager.
savedInstanceState.putSerializable(KEY_LAYOUT_MANAGER, mCurrentLayoutManagerType);
super.onSaveInstanceState(savedInstanceState);
}
#Override
public Loader<List<Store>> onCreateLoader(int id, Bundle args) {
mContentReslover = getActivity().getContentResolver();
return new StoreSectionLoader(getActivity(), RetailFinderContract.URI_STORES_TABLE, mContentReslover);
}
#Override
public void onLoadFinished(Loader<List<Store>> loader, List<Store> store) {
mAdapter.setData(store);
mStore = store;
}
#Override
public void onLoaderReset(Loader<List<Store>> loader) {
mAdapter.setData(null);
}
}
I am trying to launch an activity from a recyclerview's item using OnClick method. I made an interface and used getAdapterPostion in the adapter. But the Activity is not launching. Here's my code:
Interface that I created in my Adapter:
public interface Clicklistener{
public void itemClicked(View view,int position);
}
}
Setter method for ClickListener:
public void setclickListener(Clicklistener clickListener){
this.clickListener = clickListener;
}
View Holder Method where I set the OnClickListener:
public class ViewHolderListMovies extends RecyclerView.ViewHolder implements View.OnClickListener {
private ImageView movieThumbnail;
private TextView movieTitle;
private TextView movieYear;
public ViewHolderListMovies(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
movieThumbnail = (ImageView) itemView.findViewById(R.id.video_poster);
movieTitle = (TextView) itemView.findViewById(R.id.video_name);
movieYear = (TextView) itemView.findViewById(R.id.video_year);
}
#Override
public void onClick(View v) {
if(clickListener!=null){
clickListener.itemClicked(v,getAdapterPosition());
}
}
The I Initialised the the interface in the fragment:
listMoviesAdapter.setclickListener(this);
At last I started an intent in in the fragment to call the needed Activity:
#Override
public void itemClicked(View view, int position) {
startActivity(new Intent(getActivity(),MovieDetailsActivity.class));
}
Any Help is appreciated. Thanks!
Initialise the setoncliklistener in method onBindViewHolder. Example, may be help
public class HistoryAdapter extends RecyclerView.Adapter<HistoryAdapter.ViewHolder> {
private Context mContext;
private List<String> mDataSet;
private List<String> mIdevent;
public HistoryAdapter(Context context, List<String> dataSet, List<String> idevent, List<String> askPrice,
List<String> bidPrice, List<String> Profit) {
mContext = context;
mDataSet = dataSet;
mIdevent = idevent;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(mContext)
.inflate(R.layout.layout_list_history, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Picasso.with(mContext).load(R.drawable.add2new).into(holder.image);
holder.text.setText(mDataSet.get(position));
holder.setClickListener(new HistoryAdapter.ViewHolder.ClickListener() {
public void onClick(View v, int pos, boolean isLongClick) {
if (isLongClick) {
// View v at position pos is long-clicked.
String poslx = pos + "";
String menax = mDataSet.get(pos);
Toast.makeText(mContext, "longclick pos. " + poslx + " pair " + menax, Toast.LENGTH_SHORT).show();
} else {
// View v at position pos is clicked.
//String possx = pos + "";
String poslx = pos + "";
String event2 = mDataSet.get(pos);
String id2 = mIdevent.get(pos);
Toast.makeText(mContext, "shortclick pos. " + poslx + " pair " + event2, Toast.LENGTH_SHORT).show();
//toggleSelection(pos);
Intent i = new Intent(mContext, HistoryCandlesActivity.class);
Bundle extras = new Bundle();
extras.putString("eventx", event2);
extras.putString("idx", id2);
extras.putInt("whatspage", 0);
i.putExtras(extras);
v.getContext().startActivity(i);
}
}
});
}
#Override
public int getItemCount() {
return mDataSet.size();
}
public void remove(int position) {
mDataSet.remove(position);
notifyItemRemoved(position);
}
public void add(String text, int position) {
mDataSet.add(position, text);
notifyItemInserted(position);
}
static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
public ImageView image;
public TextView text;
private ClickListener clickListener;
public ViewHolder(View itemView) {
super(itemView);
image = (ImageView) itemView.findViewById(R.id.image);
text = (TextView) itemView.findViewById(R.id.text);
// We set listeners to the whole item view, but we could also
// specify listeners for the title or the icon.
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
/* Interface for handling clicks - both normal and long ones. */
public interface ClickListener {
/**
* Called when the view is clicked.
*
* #param v view that is clicked
* #param position of the clicked item
* #param isLongClick true if long click, false otherwise
*/
public void onClick(View v, int position, boolean isLongClick);
}
/* Setter for listener. */
public void setClickListener(ClickListener clickListener) {
this.clickListener = clickListener;
}
#Override
public void onClick(View v) {
// If not long clicked, pass last variable as false.
clickListener.onClick(v, getPosition(), false);
}
#Override
public boolean onLongClick(View v) {
// If long clicked, passed last variable as true.
clickListener.onClick(v, getPosition(), true);
return true;
}
}
}
I have a listview with a getCount() of 7. I want all 7 items to be shown regardless if any data from my database is available to populate them. If no data is available then an item should just be blank with predetermined text.
When I have not hardcoded 7 database entries beforehand to go into the 7 views then I get an indexoutofbound exception when running the app due to the 7 items not being able to be populated accordingly. This happens in ListMealsAdapter.java when method Meal currentItem = getItem(position); is called and triggers public Meal getItem(int position).
I am looking for a condition statement that I can use for my listview/adapter that can handle an empty database so that the index does not go out of bounds. Also, is the BaseAdapter suited for what I want to do?
MainActivity.java
public class MainActivity extends BaseActivity {
public static final String TAG = "MainActivity";
private ListView mListviewMeals;
private MealDAO mMealDao;
private List<Meal> mListMeals;
private ListMealsAdapter mAdapter;
private SQLiteDatabase mDatabase;
DatabaseHelper mDbHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
activateToolbar(1);
// initialize views
initViews();
// fill the dailyListView
mMealDao = new MealDAO(this);
mListMeals = mMealDao.getAllMeals();
mAdapter = new ListMealsAdapter(this, mListMeals, MainActivity.this);
mListviewMeals.setAdapter(mAdapter);
}
private void initViews() {
this.mListviewMeals = (ListView) findViewById(R.id.view_daily_list);
}
ListMealsAdapter.java
public class ListMealsAdapter extends BaseAdapter {
public static final String TAG = "ListMealsAdapter";
Activity mActivity;
private List<Meal> mItems;
private LayoutInflater mInflater;
public ListMealsAdapter(Context context, List<Meal> listMeals, Activity activity) {
super();
mActivity = activity;
this.setItems(listMeals);
this.mInflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return 7;
}
#Override
public Meal getItem(int position) {
return (getItems() != null && !getItems().isEmpty()) ? getItems().get(position) : null;
}
#Override
public long getItemId(int position) {
return (getItems() != null && !getItems().isEmpty()) ? getItems().get(position).getId() : position;
}
#Override
public View getView(int position, final View convertView, final ViewGroup parent) {
View v = convertView;
final ViewHolder holder;
if (v == null) {
v = mInflater.inflate(R.layout.list_item_daily, parent, false);
holder = new ViewHolder();
holder.txtDescription = (TextView) v.findViewById(R.id.txtBreakfast);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
// fill row data
Meal currentItem = getItem(position);
if (currentItem != null) {
holder.txtDescription.setText(currentItem.getDescription());
}
return v;
}
public List<Meal> getItems() {
return mItems;
}
public void setItems(List<Meal> mItems) {
this.mItems = mItems;
}
class ViewHolder {
TextView txtDescription;
}
}
Meal.java
public class Meal implements Serializable {
public static final String TAG = "Meal";
private static final long serialVersionUID = -7406082437623008161L;
private long mId;
private int mType;
private String mDescription;
public Meal() {
}
public Meal(int type, String description) {
this.mType = type;
this.mDescription = description;
}
public long getId() {
return mId;
}
public void setId(long mId) {
this.mId = mId;
}
public int getType() {
return mType;
}
public void setType(int mType) {
this.mType = mType;
}
public String getDescription() {
return mDescription;
}
public void setDescription(String mDescription) {
this.mDescription = mDescription;
}
}
MealDAO.java
public class MealDAO {
public static final String TAG = "MealDAO";
private SQLiteDatabase mDatabase;
private DatabaseHelper mDbHelper;
private Context mContext;
private String[] mAllColumns = { DatabaseHelper.COLUMN_MEAL_ID,
DatabaseHelper.COLUMN_MEAL_TYPE, DatabaseHelper.COLUMN_MEAL_DESCRIPTION};
public MealDAO(Context context) {
this.mContext = context;
mDbHelper = new DatabaseHelper(context);
// open the database
try {
open();
} catch (SQLException e) {
Log.e(TAG, "SQLException on opening database " + e.getMessage());
e.printStackTrace();
}
}
public void open() throws SQLException {
mDatabase = mDbHelper.getWritableDatabase();
}
public void close() {
mDbHelper.close();
}
public List<Meal> getAllMeals() {
List<Meal> listMeals = new ArrayList<Meal>();
Cursor query = mDatabase.rawQuery("SELECT * from meal", null);
if(query.moveToFirst()) {
do {
// Cycle through all records
Meal meal = cursorToMeal(query);
listMeals.add(meal);
} while(query.moveToNext());
}
return listMeals;
}
public Meal getMealById(long id) {
Cursor cursor = mDatabase.query(DatabaseHelper.TABLE_MEALS, mAllColumns,
DatabaseHelper.COLUMN_MEAL_ID + " = ?",
new String[] { String.valueOf(id) }, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
}
Meal meal = cursorToMeal(cursor);
return meal;
}
protected Meal cursorToMeal(Cursor cursor) {
Meal meal = new Meal();
meal.setId(cursor.getLong(0));
meal.setType(cursor.getInt(1));
meal.setDescription(cursor.getString(2));
return meal;
}
}
After a LOT of trial and error I finally found an acceptable solution to my problem. What I did was to add a default row to my database for the view items that I wanted to have a predetermined database entry when no data had been entered beforehand.
I then made sure to start at index 2, making sure that index 1 would be reserved for my default value. If the index comes out of bounds then the exception is caught and the default database entry will be added to the array.
public Meal getItem(int position) {
Meal result;
try {
result = (getItems() != null && !getItems().isEmpty()) ? getItems().get(position) : null;
} catch (Exception e) {
Meal default = getItem(0);
return default;
}
return result;
}
Meal currentItem = getItem(position + 1);
if (currentItem != null) {
holder.txtDescription.setText(currentItem.getDescription());
}
With that change things have been running smooth ever since. I hope this can help someone else as well.