Android ListView Adapter not working correctly - java

I've been attempting to upgrade an old app I made in college, including adding a listview to show data from Last.FM. The idea is having a main text with subtext under it, but the adapter I put together just isn't working. I've tried a good number of options, and the most recent is giving me a "Attempt to invoke virtual method on a null object reference" error, a previous try got a "Cannot cast Activity to Application" error.
Relevant code sections:
Main Activity adapter section:
ListView lv;
final Dialog dialog = new Dialog(MainActivity.this);
dialog.setContentView(R.layout.summarylayout);
dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT);
lv = (ListView) dialog.findViewById(R.id.itemList); //Listview name
artistAdapter = new itemAdapter(getApplicationContext(), //Changed from ArrayAdapter<Item>
R.layout.custom_listview, //R.layout.custom_listview if itemAdapter works
result.toArray(new Item[] {}));
lv.setAdapter(artistAdapter);
lv.setOnItemClickListener(new MyOIListener());
Button closeButton = (Button) dialog
.findViewById(R.id.closeBtn);
// if button is clicked, close the custom dialog
closeButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
tracks = false;
dialog.dismiss();
}
});
The custom Adapter itself (Commented sections are previous attempts):
public class itemAdapter extends ArrayAdapter<Item>{
Context context;
int layoutResourceId;
Item data[] = null;
public itemAdapter(Context context, int layoutResourceId, Item[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
// ItemHolder holder = null;
Item rowIn = new Item();
TextView main;
TextView sub;
if(row == null)
{
//LayoutInflater inflater = ((Application)context).getLayoutInflater();
//row = inflater.inflate(layoutResourceId, parent, false);
//row = LayoutInflater.from(getActivity()).inflate(R.layout.custom_listview, parent, false);
LayoutInflater inflater = LayoutInflater.from(this.getContext());
row = inflater.inflate(layoutResourceId, parent, false);
//holder = new ItemHolder();
//rowIn = new Item();
}
else
{
rowIn = (Item) row.getTag();
}
main = (TextView)row.findViewById(R.id.mainText);
sub = (TextView)row.findViewById(R.id.subText);
row.setTag(rowIn);
Item temp = data[position];
main.setText(temp.getTitle());
sub.setText(temp.getExtra());
return row;
}
/* static class ItemHolder
{
TextView mainText;
TextView subText;
}*/
}
The "Item" class is simply a holder for text/URLs parsed from the Last.FM api request.
I realize this is a question asked often, but 3 days of attempts and searching hasn't helped me out much. Any help would be appreciated

You're passnig the applicationContext to your adapter. Pass your Activity by:
artistAdapter = new itemAdapter(MainActivity.this, //Changed from ArrayAdapter<Item>
R.layout.custom_listview, //R.layout.custom_listview if itemAdapter works
result.toArray(new Item[] {}));

Your getView method was wrong, actually you will face a null variable there when getting the data from the tag.
This one should work for you, it is using ViewHolder Pattern
public class itemAdapter extends ArrayAdapter<Item> {
Context context;
int layoutResourceId;
Item data[] = null;
public itemAdapter(Context context, int layoutResourceId, Item[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ItemHolder holder = null;
if (convertView == null) {
//LayoutInflater inflater = ((Application)context).getLayoutInflater();
//row = inflater.inflate(layoutResourceId, parent, false);
//row = LayoutInflater.from(getActivity()).inflate(R.layout.custom_listview, parent, false);
LayoutInflater inflater = ((Activity) this.context).getLayoutInflater();
convertView = inflater.inflate(layoutResourceId, parent, false);
holder = new ItemHolder();
holder.mainText = row.findViewById(R.id.mainText);
holder.subText = row.findViewById(R.id.subText);
convertView.setTag(holder);
} else {
holder = (ItemHolder) convertView.getTag();
}
Item temp = data[position];
if(temp != null) {
holder.mainText.setText(temp.getTitle());
holder.subText.setText(temp.getExtra());
}
return convertView;
}
static class ItemHolder {
TextView mainText;
TextView subText;
}
}
And as #vinitius said, pass your Activity context to the adapter.

Related

populating Spinner nested in ListView Rows (Android)

I have a list view where each row displays the name of some inventory item, its quantity available, and a spinner to select the amount of the item to buy (when clicking make purchase at the bottom of the page, the selected amount of each spinner is grabbed and processed).
I currently have a loop that iterates over the rows and grabs the spinner by its identifier. It uses the position of the row to access another array that contains the corresponding qty of the item show in this position. It uses this qty as a stopping point for another nested loop that creates an ArrayList of numbers up to the given qty (so a user cannot select more than what is available). The ArrayList is then popped into a custom ArrayAdapter as the data field but for some reason the ArrayAdapter is not populating the spinner. What's missing??
Heres the relevant code
public class PlaceOrder extends Activity {
ArrayList<Item> items;
ArrayList<Customer> customers;
int position;
ListView orderList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_place_order);
Intent data = getIntent();
items = data.getParcelableArrayListExtra("items");
customers = data.getParcelableArrayListExtra("customers");
position = data.getIntExtra("position", 0);
orderList = (ListView) findViewById(R.id.purchaseList);
PurchasedItemAdapter itemAdapter = new PurchasedItemAdapter(this, R.layout.purchase_table_row, items);
orderList.setAdapter(itemAdapter);
for (int i = 0; i < orderList.getCount(); i++) {
View view = orderList.getAdapter().getView(i, null, null);
Spinner spinner = (Spinner) view.findViewById(R.id.purchase_table_spinner);
int stop = items.get(i).qtyAvailable;
ArrayList<String> stringList = new ArrayList<String>();
for (int k = 0; k <= stop; k++) {
stringList.add(String.format("%d", k));
}
SpinnerAdapter spinnerAdapter = new SpinnerAdapter(this, R.layout.simple_spinner_item, stringList);
spinner.setAdapter(spinnerAdapter);
}
}
Adapter Class...
public class SpinnerAdapter extends ArrayAdapter<String> {
Context context;
int layoutResourceId;
ArrayList<String> data = null;
public SpinnerAdapter (Context context, int layoutResourceId, ArrayList<String> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder holder = null;
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ViewHolder();
holder.qty = (TextView)row.findViewById(R.id.simple_spinner_text);
row.setTag(holder);
} else {
holder = (ViewHolder)row.getTag();
}
holder.qty.setText(data.get(position));
return row;
}
static class ViewHolder {
TextView qty;
}
}
Listview Adapter..
public class PurchasedItemAdapter extends ArrayAdapter<Item> {
Context context;
int layoutResourceId;
ArrayList<Item> data = null;
public PurchasedItemAdapter(Context context, int layoutResourceId, ArrayList<Item> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ItemHolder holder = null;
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ItemHolder();
holder.name = (TextView)row.findViewById(R.id.purchase_table_itemName);
holder.qty = (TextView)row.findViewById(R.id.purchase_table_qty);
row.setTag(holder);
} else {
holder = (ItemHolder)row.getTag();
}
Item item = data.get(position);
holder.name.setText(item.name);
holder.qty.setText(String.format("%d", item.qtyAvailable));
return row;
}
static class ItemHolder {
TextView name;
TextView qty;
}
}
If PurchasedItemAdapter is your custom list adapter spinnerAdapter for each row(if the spinner is not same for each row) is suitable to set inside the PurchasedItemAdapter class or at least it is better to set spinner adapter before PurchasedItemAdapter
" the selected amount of each spinner is grabbed and processed" so each row of your list has a spinner why don't you set it inside PurchaseItemAdapter and add a spinner item in view Holder class as well...I would do so

How can use listView in fragment?

I am trying to use listview in Fragment but it does not work when I press the selected row.
// Group1ListViewFragment.java
private ListView listview1;
public Group1ListViewFragment(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.group1_list_view_fragment, container, false);
Team[] team_data = new Team[]
{
new Team(R.drawable.ic_launcher, "Arsenal"),
new Team(R.drawable.ic_launcher, "Chelsea"),
new Team(R.drawable.ic_launcher, "Everton"),
new Team(R.drawable.ic_launcher, "Liverpool"),
new Team(R.drawable.ic_launcher, "Manchester United")
};
ListView listview1 = (ListView)rootView.findViewById(R.id.listView1);
// Using the adapter to connect between item view and the photo array
listview1.setAdapter(new TeamAdapter(getActivity(), 0, team_data));
return rootView;
}
Also, i make a adapter to connect listView and array
This is TeamAdapter.java
public TeamAdapter(Context context, int layoutResourceId, Team[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
TeamHolder holder = null;
if (row == null) {
// LayoutInflater inflater = ((Activity) context).getLayoutInflater();
// Ref: http://stackoverflow.com/questions/7803771/call-to-getlayoutinflater-in-places-not-in-activity
LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
row = inflater.inflate(layoutResourceId, parent, false);
holder = new TeamHolder();
holder.imgIcon = (ImageView) row.findViewById(R.id.imgIcon);
holder.txtTitle = (TextView) row.findViewById(R.id.txtTitle);
row.setTag(holder);
} else {
holder = (TeamHolder) row.getTag();
}
Team team = data[position];
holder.txtTitle.setText(team.title);
holder.imgIcon.setImageResource(team.icon);
return row;
}
static class TeamHolder {
ImageView imgIcon;
TextView txtTitle;
}
you forget pass listview row Xml in adapter class
Replace
listview1.setAdapter(new TeamAdapter(getActivity(), 0, team_data));
with
listview1.setAdapter(new TeamAdapter(getActivity(), R.layout.yourrowxml, team_data));
thats it...

multiselection listView contains checkBoxes

I have ListView with check boxes the app delete the checked items ;; and should delet teh items that have the same id with the checked items :
here's my code
private class CAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private ArrayList<Entity> list;
private Context context;
String Status;
CAdapter(Context context,
ArrayList<Entity> getC) {
this.context = context;
this.list = getC;
Status="";
mInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
class ViewHolder {
TextView Name;
TextView Desc;
Button deleteBtn;
CheckBox CBox;
}
public int getCount() {
return list.size();
}
public Object getItem(int position) {
return list.get(position);
}
public long getItemId(int position) {
return position;
}
#SuppressLint("NewApi")
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
final CEntity CObj = list.get(position);
if (convertView == null) {
convertView = mInflater.inflate(
R.layout.custom_list_view_confirmed, parent,
false);
holder = new ViewHolder();
holder.Name = (TextView) convertView
.findViewById(R.id.Name);
holder.Desc = (TextView) convertView
.findViewById(R.id.activity1);
holder.deleteBtn = (Button) convertView
.findViewById(R.id.deleteBtn);
holder.CBox=(CheckBox) convertView.findViewById(R.id.isCheck);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
if (CObj.getMystatus().equals(
context.getResources().getString(R.string.course_status_delete))) {
holder.status.setTextColor(Color.RED);
} else if (attemptedCourseObj.getMystatus().equals(
context.getResources().getString(R.string.course_status_pending))) {
holder.status.setTextColor(Color.GREEN);
} else if (attemptedCourseObj.getMystatus().equals(
context.getResources().getString(R.string.course_status_update))) {
holder.status.setTextColor(Color.BLUE);
}
holder.Name.setText(attemptedCourseObj.getCourseName());
holder.CBox.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(holder.CBox.isChecked()){
if(list.contains(getItem(position))){
list.remove(getItem(position));
}
}
}
});
//
return convertView;
}
}
the problem is when delete the checked it dosent delete the item that have the same id .
int pos=Data.CList.size();
SparseBooleanArray checked=CListView.getCheckedItemPositions();
for (int n = pos; n > 0; n--){
if (checked.get(n)){
code=Data.inList.get(n).getCCode();
Data.inList.remove(n);
}else if(CList.get(n).equal(code){
Data.inList.remove(n);
}
try to refresh the list with notifydatasetchanged and be sure that you delete the entire object from the list
You need to inform your adapter with the new modifications by giving the adapter the new dataset after removing the deleted elements from it and notify with the changes. You can do this as the following:
1)Add method into your adapter to set the new data as following:
public void setNewData(ArrayList<Entity> newEntities){
this.list = newEntities;
}
2)From the activity or the fragment call the previous method with the new data and call this line to notify the adapter with the changes
myAdapter.setNewData(myNewEntities);
myAdapter.notifyDataSetChanges();
Read this answer for more info about NotifyDataSetChanges() method

Android : want to access to a textview in a viewholder in my mainactivity

I am so sorry for my bad English, but here is my problem :
I use a custom ListView like ArrayAdapter and I create my ArrayAdapter as a intern class in my main Activity like that :
/*This is my Main Activity*/
public class KhassaideActivity extends Activity {
ViewHolder holder;
KhassaideAdapterbi listadapter ;
ListView l ;
#Override
protected void onCreate(Bundle savedInstanceState) {
l= (ListView) findViewById(R.id.listDieuzbou);
listadapter = new KhassaideAdapterbi(this, R.layout.affichage_khassaide, rowItems);
l.setAdapter(listadapter);
}
/*This is my intern class ArrayAdapter*/
private class KhassaideAdapterbi extends ArrayAdapter<RowItem>{
Context context;
public KhassaideAdapterbi(Context context, int resourceId,
List<RowItem> items) {
super(context, resourceId, items);
this.context = context;
}
public class ViewHolder {
ImageView imageView;
TextView trad;
TextView trans;
TextView number;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
RowItem rowItem = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.affichage_khassaide, null);
holder.number = (TextView) convertView.findViewById(R.id.number);
holder.trad = (TextView) convertView.findViewById(R.id.traduction);
holder.trans = (TextView) convertView.findViewById(R.id.transcription);
holder.imageView = (ImageView) convertView.findViewById(R.id.arabe);
convertView.setTag(holder);
}
else
holder = (ViewHolder) convertView.getTag();
holder.trad.setText(rowItem.getTitle());
holder.trans.setText(rowItem.getDesc());
holder.imageView.setImageResource(rowItem.getImageId());
holder.number.setText(rowItem.getNumber());
return convertView;
}
}
So in my main Activity I want to access and share the values of the two TextView when the user click on a menu item like that :
case R.id.action_share:
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, listadapter.holder.trad.getText());
sendIntent.setType("text/plain");
startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to)));
But I get a NullPointerException at this line listadapter.holder.trad.getText()
Is anyone have a solution for that? Thank you in advance. And sorry once again for this bad english
you should change this....
private class KhassaideAdapterbi extends ArrayAdapter<RowItem>{
Context context;
List<RowItem> Rowitems;
public KhassaideAdapterbi(Context context, int resourceId,
List<RowItem> items) {
super(context, resourceId, items);
this.context = context;
this.Rowitems = items;
}
now get data from Rowitems ...

Android viewholder onclick updates more instances

For my android application i'm using the ViewHolder pattern.
Whenever i click on an imageview in my listview the row get updated but other rows are also getting updated.
Whenever i click the "like" button other images also receive the image that the are liked by the user. How is this possible?
Here is my viewholder code:
public class MyAdapter extends ArrayAdapter<MyModel> {
Context context;
int layoutResourceId;
List<MyModel> data = null;
public MyAdapter(Context context, int layoutResourceId,
List<MyModel> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
final BlockHolder holder;
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new BlockHolder();
holder.imgIcon = (ImageView) row.findViewById(R.id.imgIcon);
holder.totalVotes = (TextView) row.findViewById(R.id.totalVotes);
holder.likeIcon = (ImageView) row.findViewById(R.id.likeIcon);
holder.dislikeIcon = (ImageView) row.findViewById(R.id.dislikeIcon);
holder.saveIcon = (ImageView) row.findViewById(R.id.saveIcon);
row.setTag(holder);
} else {
holder = (BlockHolder) row.getTag();
}
MyModel myBlock = data.get(position);
ImageLoader.getInstance().displayImage(myBlock.getImage(),
holder.imgIcon);
final int totalLikes = myBlock.getLikes() - myBlock.getDislikes();
holder.totalVotes.setText(totalLikes + " likes");
final ImageView like = holder.likeIcon;
holder.likeIcon.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// ALSO UPDATES OTHER VIEWS...
holder.likeIcon.setBackgroundResource(R.drawable.thumbs_up_mouse);
}
});
return row;
}
private static class BlockHolder{
ImageView imgIcon;
TextView totalVotes;
ImageView dislikeIcon;
ImageView likeIcon;
ImageView saveIcon;
}

Categories