I am writing a music player application with playlists, and I am trying to display the songs that have been chosen. All of the code for that works fine, but when a song is added, the listView won't update. I have searched extensively online, but cannot figure out how to fix it. I ended up trying to call leftAdapter.notifyDataSetChanged(); to update the list, but it throws the error:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ArrayAdapter.notifyDataSetChanged()' on a null object reference
I have also tried calling the initializing method (createLeftList()) but it duplicates all of the items in the list.
Method called to initialize listview:
public void createLeftList() {
DatabaseHandler db = new DatabaseHandler(this);
leftSongView = (ListView) findViewById(R.id.left_playlistView);
db.getAllsongs();
ArrayAdapter<String> leftAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, ArrayofName);
leftSongView.setAdapter(leftAdapter);
leftSongView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
Toast.makeText(getApplicationContext(), ((TextView) v).getText(), Toast.LENGTH_SHORT).show();
}
});
}
Method to fetch list and send to listview
public List<LeftPlaylist> getAllsongs() {
List<LeftPlaylist> leftPlaylistList = new ArrayList<LeftPlaylist>();
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_PLAYLIST;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
LeftPlaylist leftPlaylist = new LeftPlaylist();
leftPlaylist.setID(Integer.parseInt(cursor.getString(0)));
leftPlaylist.setName(cursor.getString(1));
leftPlaylist.setPath(cursor.getString(2));
String name = cursor.getString(1) +"\n"+ cursor.getString(2);
ListenPage.ArrayofName.add(name);
// Adding song to list
leftPlaylistList.add(leftPlaylist);
} while (cursor.moveToNext());
}
Method called to update the listview after modifying it:
public void updateLeftList(){
leftAdapter.notifyDataSetChanged();
}
Any help would be greatly appreciated!
Here is my SongAdapter code:
public class SongAdapter extends BaseAdapter {
private ArrayList<Song> songs;
private LayoutInflater songInf;
public SongAdapter(Context c, ArrayList<Song>theSongs){
songs=theSongs;
songInf=LayoutInflater.from(c);
}
#Override
public int getCount() {
return songs.size();
}
#Override
public Object getItem(int arg0) {
return null;
}
#Override
public long getItemId(int arg0) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//map to song layout
LinearLayout songLay = (LinearLayout)songInf.inflate
(R.layout.song, parent, false);
//get title and artist views
TextView songView = (TextView)songLay.findViewById(R.id.song_title);
TextView artistView = (TextView)songLay.findViewById(R.id.song_artist);
//get song using position
Song currSong = songs.get(position);
//get title and artist strings
songView.setText(currSong.getTitle());
artistView.setText(currSong.getArtist());
//set position as tag
songLay.setTag(position);
return songLay;
}
}
Do this in your Activity Class.
public class MyActivity extends Activity {
private SongListAdapter _songListAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
createLeftList();
}
private void createLeftList(){
DatabaseHandler db = new DatabaseHandler(this);
ListView leftSongView = (ListView) findViewById(R.id.left_playlistView);
_songListAdapter = new SongListAdapter(this, db.getAllsongs());
leftSongView.setAdapter(_songListAdapter);
}
//TODO use this whenever you wanna update your list.
public void updateSongView(List<String> songsList){
if(_songListAdapter != null && songsList != null){
_songListAdapter.updateMusicList(songsList);
}
}
}
Then create and Adapter class and follow the pattern.
public class SongListAdapter extends BaseAdapter{
private Context _context;
private List<String> musicList = new ArrayList();
public SongListAdapter(Context context, List<String> musicList){
_context = context;
this.musicList.clear();
this.musicList.addAll(musicList);
}
public void updateMusicList(List<String> musicList){
this.musicList.clear();
this.musicList.addAll(musicList);
notifyDataSetChanged();
}
#Override
public int getCount() {
return musicList.size();
}
#Override
public Object getItem(int position) {
return musicList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = LayoutInflater.from(_context).inflate(R.layout.music_view, parent, false);
// TODO folow view holder pattern.
}
String music = (String) getItem(position);
if(music != null){
//TODO update your views Here
}
return convertView;
}
#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
//TODO peform any custon action when this is called if needed.
}
}
Related
I'm getting a variable data sent from activity to my adapter by using
sendData method, but every time when I try to access it in my getView method it resets to 0, please help. I've tried to debug code to check if the data from an activity is passing and it looks ok. I also created a getNumb method but still, the variable resets to 0. Here is my adapter code:
public class WorkoutListAdapterTwo extends BaseAdapter {
private int y;
public WorkoutListAdapterTwo() {
}
public int sendData(int x){
this.y = x;
return y;
}
public int getNumb(){
return this.y;
}
private static LayoutInflater mLayoutInflater = null;
public WorkoutListAdapterTwo(Activity ctx) {
this.mLayoutInflater = ctx.getLayoutInflater();
}
#Override
public int getCount() {
return WorkoutContentTwo.WORKOUTSTWO.size();
}
#Override
public Object getItem(int position) {
return WorkoutContentTwo.WORKOUTSTWO.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
int j = getNumb();
WorkoutTwo workout = (WorkoutTwo) getItem(j);
String [] arrOfStrings = workout.name.split(",");
if (convertView == null) {
convertView = mLayoutInflater.inflate(R.layout.adapter_workout_row, parent, false);
holder = new ViewHolder();
holder.id = (TextView) convertView.findViewById(R.id.workout_id);
holder.name = (TextView) convertView.findViewById(R.id.workout_name);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// Set the content for the ListView row
//holder.id.setText(workout.id);
//holder.name.setText(arrOfStrings[i]);
holder.id.setText(Integer.toString(position+1));
holder.name.setText(workout.ArrList[position]);
// Set the color for the ListView row
holder.id.setBackgroundColor(workout.dark);
holder.name.setBackgroundColor(workout.light);
return convertView;
}
Here I'm adding the code where I'm calling my method:
public void onItemSelected(int position) {
// Start the detail activity for the selected workout ID.
Intent detailIntent = new Intent(this, WorkoutDetailActivityTwo.class);
detailIntent.putExtra(WorkoutDetailFragmentTwo.ARG_WORKOUT_POS, position);
WorkoutListAdapterTwo newAdd = new WorkoutListAdapterTwo();
newAdd.sendData(position);
newAdd.notifyDataSetChanged();
startActivity(detailIntent);
}
Are you notifying your adapter to update views after updating the value? If your sendData() is not called until after the adapter has done it's first draw, you will need to call notifyDataSetChanged() so that the adapter knows there are new values that should be used to update your views.
You have to make a interface or you can a use notifyDataSetChanged depends on the use if you are doing search operation then use the notifyDataSetChanged method but if you want to send some data then
Fragment or activity
public class ExampleFragment extends Fragment implements MyAdapter.SuccessResponse{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View contentView = inflater.inflate(R.layout.my_layout, container, false);
MyAdapter myAdapter = new MyAdapter(getActivity(), 0);
myAdapter.successResponse = this;
return contentView;
}
#Override
public void onSuccess() {
}
}
The adapter code
class MyAdapter extends ArrayAdapter{
SuccessResponse successResponse;
public MyAdapter(Context context, int resource) {
super(context, resource);
}
public interface SuccessResponse{
void onSuccess();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//ur views
linearLayout.setOnClickListener(new View.OnClickListener{
#Override
public void onClick (View view){
if(successResponse!=null)
successResponse.onSuccess();
}
})
}
}
You can use any type of adapter i am use arrayadaper here.
Currently I'm adding a custom row (contains and edit text and a plus and minus for adding/removing a row) to a list view. However, each time a row is added the contents from all edit texts are wiped.
public class ingredientView extends BaseAdapter implements ListAdapter {
private ArrayList<String> list = new ArrayList<String>();
private Context context;
public ingredientView(ArrayList<String> list, Context context) {
this.list = list;
this.context = context;
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int pos) {
return list.get(pos);
}
#Override
public long getItemId(int pos) {
return 0;
//just return 0 if your list items do not have an Id variable.
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.ingredient_item, null);
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(context, android.R.layout.simple_dropdown_item_1line, loadedFood);
//Handle TextView and display string from your list
InstantAutoComplete listItemText = (InstantAutoComplete) view.findViewById(R.id.recipe_ingredients);
listItemText.setAdapter(adapter);
listItemText.setText(list.get(position));
//Handle buttons and add onClickListeners
ImageButton deleteBtn = (ImageButton)view.findViewById(R.id.ingredient_minus_button);
ImageButton addBtn = (ImageButton)view.findViewById(R.id.ingredient_plus_button);
deleteBtn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
//do something
if (list.size()>1){
list.remove(position); //or some other task
notifyDataSetChanged();}
}
});
addBtn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
//do something
list.add(position+1,"");
notifyDataSetChanged();
}
});
return view;
}
private static final String[] loadedFood = new String[]{
"eggs","milk","butter","flour"
};
}
I'm new at android. and I want to load a new template which contains two button on a selected item of grid view object.
Is that possible.
I added a gridview to my project and by using base adapter a template was loaded to each item of gridview. But what I want is that when I clicked an item of gridview, I want to load a new template (layout) to the selected item.
THE PROBLEM WAS SOLVED, followings are the edited codes
Base Adapter
public class KategoriAdapter extends BaseAdapter{
private Context mContext;
private String[] categoryValues;
private Bitmap[] pictures;
//indicate that positon for new template
private int mNewTemplatePos = -1;
public KategoriAdapter(Context context, String[] categoryValues, Bitmap[] pictures) {
this.mContext = context;
this.categoryValues = categoryValues;
this.pictures = pictures;
}
//apply new template to positon
public void useNewTemplate(int pos) {
mNewTemplatePos =pos;
//notiy list that data has changed and the list will refresh ui itself.
notifyDataSetChanged();
}
#Override
public int getCount() {
return categoryValues.length;
}
#Override
public Object getItem(int possition) {
return null;
}
#Override
public long getItemId(int possition) {
return 0;
}
#Override
public View getView(int possition, View convertView, ViewGroup parent) {
final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int posId = mNewTemplatePos;
if (convertView == null){
if (mNewTemplatePos ==possition){
convertView = getNewTemplate(inflater,possition);
}else {
convertView = getNormalTemplate(inflater,possition);
}
}else {
if (posId==possition){
convertView = getNewTemplate(inflater,possition);
}else{
convertView = getNormalTemplate(inflater,possition);
}
}
return convertView;
}
private View getNormalTemplate(LayoutInflater inflater, int possition) {
final View grid = inflater.inflate(R.layout.kategoriler_list_item, null);
TextView cName = (TextView) grid.findViewById(R.id.grid_item_ad);
ImageView categoryPictures = (ImageView) grid.findViewById(R.id.grid_item_resim);
cName.setText(categoryValues[possition]);
categoryPictures.setImageBitmap(pictures[possition]);
return grid;
}
private View getNewTemplate(LayoutInflater inflater, int possition) {
final View grid = inflater.inflate(R.layout.kategori_secenek_template, null);
TextView cName = (TextView) grid.findViewById(R.id.grid_item_ad);
cName.setText(categoryValues[possition]);
Button btn_nesne_tani = (Button) grid.findViewById(R.id.btn_nesneleri_taniyalim);
Button btn_cumle_kur = (Button) grid.findViewById(R.id.btn_cumle_kuralim);
btn_nesne_tani.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(mContext,"nesne",Toast.LENGTH_SHORT).show();
}
});
btn_cumle_kur.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(mContext,"cümle",Toast.LENGTH_SHORT).show();
}
});
return grid;
}
}
KategoriActivity.java
.....
final KategoriAdapter adapter = new KategoriAdapter(getApplicationContext(), mKategoriler, kategoriResimleri);
grid=(GridView)findViewById(R.id.gv_kategoriler);
grid.setAdapter(adapter);
grid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
adapter.useNewTemplate(position);
Toast.makeText(getApplicationContext(), mKategoriler[position].toString(),Toast.LENGTH_SHORT).show();
}
});
}
I have rewrite your KategoriAdapter class:
public class KategoriAdapter extends BaseAdapter {
private Context mContext;
private final String[] categoryValues;
private final Bitmap[] pictures;
//indicate that positon in list are all use new template
private List<Integer> mNewTemplatePos;
public ImageView categoryPictures;
//indicate that this is normal template view
private final String NORMAL_TEMPLATE = "NORMAL_TEMPLATE";
//indicate that this is new template view
private final String NEW_TEMPLATE = "NEW_TEMPLATE";
public KategoriAdapter(Context context, String[] categoryValues, Bitmap[] pictures) {
this.mContext = context;
this.categoryValues = categoryValues;
this.pictures = pictures;
this.mNewTemplatePos = new ArrayList<>();
}
//apply new template to positon
public void useNewTemplate(int pos) {
mNewTemplatePos.add(pos);
//notiy list that data has changed and the list will refresh ui itself.
notifyDataSetChanged();
}
#Override
public int getCount() {
return categoryValues.length;
}
#Override
public Object getItem(int possition) {
return null;
}
#Override
public long getItemId(int possition) {
return 0;
}
#Override
public View getView(int possition, View convertView, ViewGroup parent) {
final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
if (mNewTemplatePos.contains(possition)) {
convertView = getNewTemplate(inflater, possition);
//use tag to indicate the type of the template
convertView.setTag(NEW_TEMPLATE);
} else {
convertView = getNormalTemplate(inflater, possition);
convertView.setTag(NORMAL_TEMPLATE);
}
} else {
switch ((String) convertView.getTag()) {
case NORMAL_TEMPLATE:
//convertView is the normal template view but you need a new template view in possition
if (mNewTemplatePos.contains(possition))
convertView = getNewTemplate(inflater, possition);
break;
case NEW_TEMPLATE:
//convertView is the new template view but you need a normal template view in possition
if (!mNewTemplatePos.contains(possition))
convertView = getNormalTemplate(inflater, possition);
break;
}
}
return convertView;
}
private View getNormalTemplate(LayoutInflater inflater, int possition) {
View grid = inflater.inflate(R.layout.kategoriler_list_item, null);
TextView cName = (TextView) grid.findViewById(R.id.grid_item_ad);
categoryPictures = (ImageView) grid.findViewById(R.id.grid_item_resim);
cName.setText(categoryValues[possition]);
categoryPictures.setImageBitmap(pictures[possition]);
return grid;
}
private View getNewTemplate(LayoutInflater inflater, int possition) {
// TODO: 31/08/16 inflate you new template view layout here
return youNewTemplateView;
}
}
You should determine wether if current contentView is the right template type in getView() because contentView may be one of the new template in your list when it is not null.It is convenient to use tag to indicate the template type.
When to use useNewTemplate(position)?
Just apply the position that you need to use new template to useNewTemplate() and use it in your onItemClick() method.
grid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
useNewTemplate(position);
}
});
public class delete extends BaseAdapter {
SQLiteDatabase db;
String am;
private final Context c;
private final ArrayList<String> str;
private final String[] number;
ArrayList<Integer> checks=new ArrayList<Integer>();
public delete(Context c, ArrayList<String> str, String[] number, ArrayList<Integer> checks) {
this.c = c;
this.str = str;
this.number = number;
this.checks=checks;
}
#Override
public int getCount() {
return str.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater= (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View ListView ;
if(convertView==null)
{
ListView=new View(c);
ListView=inflater.inflate(R.layout.button,null);
TextView textview=(TextView) ListView.findViewById(R.id.textView6);
textview.setText(str.get(position));
}
else
{
ListView=(View)convertView;
}
Button btnupdate=(Button)ListView.findViewById(R.id.button4);
//checkbox declaration
CheckBox chk=(CheckBox)ListView.findViewById(R.id.chk1);
btnupdate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
db=c.openOrCreateDatabase("Student",Context.MODE_PRIVATE, null);
String num = number[position];
Cursor cc=db.rawQuery("select mobile from detail where mobile='"+num+"'", null);
if (cc.moveToFirst()) {
do {
am = cc.getString(cc.getColumnIndex("mobile"));
} while (cc.moveToNext());
}
Intent i=new Intent(c,Update.class);
i.putExtra("value",am);
c.startActivity(i);
}
});
return ListView;
}
}
//It show all the data in list view with update button and check box in list view. There is delete button which is suppose to delete all the item which is checked.
//Delete button is on main activity where list view is added.
You can create a method in your DataBase class and pass the table name and entry to be deleted along with id if any.Call the method at onClick of ListView item.
public void deleteEntry(String tableName,String columnName,String id)
{
openDatabase();
database.delete(tableName, columnName + " = ?",new String[] { id });
closeDatabase();
}
I am trying to create an android application using a database from Parse.com. I am using a custom adapter to create a listview. I don't find any errors with the code and yet the listeview is not showing up. Nothing there in the logcat as well. Just the listview does not show up.
lv = (ListView)findViewById(R.id.listView);
mProgress = (ProgressBar)findViewById(R.id.check_progress);
mProgress.setVisibility(View.VISIBLE);
ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("Sellers");
query.orderByAscending("Name");
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> parseObjects, ParseException e) {
if (e == null) {
studentsList = new ArrayList<Sellers>();
for (ParseObject ob : parseObjects) {
s = new Sellers();
s.setName(ob.getString("Name").toString());
s.setAddress1(ob.getString("Address1").toString());
s.setAddress2(ob.getString("Address2").toString());
s.setShopName(ob.getString("ShopName").toString());
s.setEmail(ob.getString("Email").toString());
s.setPhone(ob.getString("Phone").toString());
s.setZipcode(ob.getString("Zipcode").toString());
studentsList.add(s);
}
adapter = new ListviewAdapter(CheckStatus.this, studentsList);
lv.setAdapter(adapter);
mProgress.setVisibility(View.GONE);
} else {
mProgress.setVisibility(View.GONE);
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
This is the activity where I am invoking the listview.
public class ListviewAdapter extends BaseAdapter{
private final static String TAG = ListviewAdapter.class.getSimpleName();
private Context activity;
private LayoutInflater inflater = null;
private List<Sellers> sellers;
int layout;
public ListviewAdapter(Context activity, List<Sellers> sellers) {
this.activity = activity;
this.sellers = sellers;
inflater = LayoutInflater.from(activity);
}
#Override
public int getCount() {
return 0;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
public class ViewHolder {
TextView name ;
TextView shop ;
TextView address1 ;
TextView address2;
TextView phone;
TextView email;
RelativeLayout rl;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
View v =view;
ViewHolder holder = new ViewHolder();
if (view == null) {
LayoutInflater li = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = li.inflate(R.layout.list_item_layout,null);
holder.name = (TextView)v.findViewById(R.id.seller_name);
holder.shop = (TextView)v.findViewById(R.id.shop_name);
holder.address1 = (TextView)v.findViewById(R.id.address1);
holder.address2 = (TextView)v.findViewById(R.id.address2);
holder.phone = (TextView)v.findViewById(R.id.phone);
holder.email = (TextView)v.findViewById(R.id.emailID);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
Sellers s = sellers.get(position);
// String a = s.Name;
// Log.d(TAG, a);
holder.name.setText(s.getName());
holder.shop.setText(s.getShopName());
holder.address1.setText(s.getAddress1());
holder.address2.setText(s.getAddress2());
holder.phone.setText(s.getPhone());
holder.email.setText(s.getEmail());
Log.d("CustomAdapter.class", "CustomAdapter");
// imageView.setImageDrawable(s.getPic());
return v;
}
}
And this is the custom adapter. There are no null pointer exceptions showing up in the logcat. I can't determine why the listview is not getting populated.
Try this;
#Override
public int getCount() {
return sellers.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position:
}
You have to implement your code on getCount() by return number of item listview will be created.