NotifyDataSetChanged cannot access in arrayadapter - android

I have a list which can be updated by user but there was an error on notifyDataSetChanged() I'm doing a to-do list, when I added notifyDataSetChanged() in array adapter it shows an error said that
error: notifyDataSetChanged() in ArrayAdapter is defined in an inaccessible class or interface
Cannot access 'notifyDataSetChanged()' in 'android.widget.ArrayAdapter'
Error happened on note_editor.
Following is my code:
note_editor (another activity)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_note_editor);
EditText editText = (EditText) findViewById(R.id.editText);
Intent intent = getIntent();
noteId = intent.getIntExtra("noteId", -1);
// note id variable transferred from main activity
if (noteId != -1) {
editText.setText(MainActivity.notes.get(noteId));
} else {
MainActivity.notes.add("");
noteId = MainActivity.notes.size() - 1;
MainActivity.arrayAdapter.notifyDataSetChanged(); //error happened here
}
MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CheckBox checkBox = (CheckBox) findViewById(R.id.checkBox);
ListView listView = (ListView) findViewById(R.id.listView);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
SharedPreferences sharedPreferences =
getApplicationContext().getSharedPreferences
("com.example.application1", Context.MODE_PRIVATE);
HashSet<String> set = (HashSet<String>)
sharedPreferences.getStringSet("notes", null);
if (set == null) {
notes.add("Example note");
} else {
notes = new ArrayList(set);
}
arrayAdapter = new CustomAdapter
(this, R.layout.simplerow, notes);
listView.setAdapter(arrayAdapter);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new
Intent(getApplicationContext(),note_editor.class);
startActivity(intent);
}
});
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick
(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(getApplicationContext(),
note_editor.class);
intent.putExtra("noteId", i);
startActivity(intent);
}
});
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
public boolean onItemLongClick
(AdapterView<?> adapterView, View view, int i, long l) {
final int itemToDelete = i;
new AlertDialog.Builder(MainActivity.this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Are you sure?")
.setMessage("Do you want to delete this note?")
.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int i) {
notes.remove(itemToDelete);
arrayAdapter.notifyDataSetChanged();
SharedPreferences sharedPreferences =
getApplicationContext().getSharedPreferences("com.example.application1",Context.MODE_PRIVATE);
HashSet<String> set = new HashSet(MainActivity.notes);
sharedPreferences.edit().putStringSet("notes", set).apply();
}
}
)
.setNegativeButton("No", null)
.show();
return true;
}
});
}
CustomAdapter
private class CustomAdapter extends ArrayAdapter<String> {
Context context;
ArrayList<String> notes = new ArrayList<>();
int layoutResourceId;
public CustomAdapter(Context context, int layoutResourceId,
ArrayList<String> objects) {
super(context, layoutResourceId, objects);
this.layoutResourceId = layoutResourceId;
this.notes=objects;
this.context=context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
CheckBox chBox = null;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.simplerow,
parent, false);
chBox = (CheckBox) convertView.findViewById(R.id.checkBox);
convertView.setTag(chBox);
chBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TextView tv = findViewById(R.id.rowTextView);
tv.setPaintFlags(tv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
arrayAdapter.notifyDataSetChanged();
}
});
}
return convertView;
}
}
Any ideas what is wrong here?

Need to change only one line. Just change arrayAdapter.notifyDataSetChanged() as below.
#Override
public void onClick(View v) {
TextView tv = findViewById(R.id.rowTextView);
tv.setPaintFlags(tv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
notifyDataSetChanged();
}
});
}
return convertView;
}
}

Error showing that the adapter object is not accessible.
You are actualy trying to update an activity already destroyed. Notify adapter from MainActivity itself.

It seems to me that the error happens because you defined your CustomAdapter as a private class, and for that reason you cannot access its methods outside of it.
The CustomAdapter should be defined as public (or package access if everything is located on the same package).
That being said, I agree with other comments pointing out that that's not the proper way to call notifyDataSetChanged (if you still have doubts about it, I suggest opening a different question for that).

Related

How to Switch Activities using a Custom ListView Adapter?

I'm trying to use a Custom ListView Adapter to switch to different activities, but am having trouble doing so, as there is an error that I can't seem to get rid of.
Relevant code
Category Table:
public class CategoryTable extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.category_table);
populateTable();
goToPreviousActivity();
}
private void populateTable() {
final ListView mListView = findViewById(R.id.listView);
Category 1 = new Category(" One");
Category 2 = new Category(" Two");
Category 3 = new Category(" Three");
Category 4 = new Category(" Four");
final ArrayList<Category> categoryList = new ArrayList<>();
categoryList.add(1);
categoryList.add(2);
categoryList.add(3);
categoryList.add(4);
CategoryListAdapter adapter = new CategoryListAdapter(this, R.layout.adapter_view_layout, categoryList);
mListView.setAdapter(adapter);
}
private void goToPreviousActivity() {
ImageButton btn = findViewById(R.id.backButton);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
}
public static Intent makeIntent(Context context) {
return new Intent(context, CategoryTable.class);
}
}
Category List Adapter:
public class CategoryListAdapter extends ArrayAdapter<Category> {
private Context mContext;
int mResource;
public CategoryListAdapter(Context context, int resource, ArrayList<Category> objects) {
super(context, resource, objects);
mContext = context;
mResource = resource;
}
#NonNull
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
String name = getItem(position).getName();
Category category = new Category(name);
final LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(mResource, parent, false);
Button catName = convertView.findViewById(R.id.btnNextTbl);
catName.setText(name);
catName.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (position == 0) {
//error -> makeIntent(android.content.Context in AllToolsTable cannot be applied to com.test.test.CategoryListAdapter
Intent intent = AllToolsTable.makeIntent(CategoryListAdapter.this);
mContext.startActivity(intent);
} else {
Toast toast = Toast.makeText(getContext(), "Clicked2", Toast.LENGTH_SHORT);
toast.show();
}
}
});
return convertView;
}
}
(I commented above the erroneous piece of code)
All Tools Table:
public class AllToolsTable extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.all_tools_table);
}
public static Intent makeIntent(Context context) {
return new Intent(context, AllToolsTable.class);
}
}
I will provide any other relevant code/details if needed.
Any help will be greatly appreciated.
//error -> makeIntent(android.content.Context in AllToolsTable cannot be applied to com.test.test.CategoryListAdapter
Intent intent = AllToolsTable.makeIntent(CategoryListAdapter.this);
Your AllToolsTable.makeIntent() method requires a Context argument. Normally you'd be fine with something like AllToolsTable.makeIntent(MainActivity.this) because Activity is a subclass of Context. However, CategoryListAdapter is not.
So you need to get your hands on a Context object somehow.
Luckily, the getView() method passes you a non-null ViewGroup parent object, and all views have a context. So you can replace your intent creation with this code:
Context context = parent.getContext();
Intent intent = AllToolsTable.makeIntent(context);

Delete Button in Listview from SQLiteDatabase

I was wondering if somebody could further explain how to implement a delete button inside a listview that is populated from an SQLite database. I've read the responses to the following question that is essentially what I'm asking as well, but I don't understand it:
How can I implement a delete button in a ListView and delete from database?
In my custom row .xml file, I included a delete button that implements the method delete() onClick. It also includes an alert dialog, by the way. Here's the code that I have so far for my delete() method; whenever I try to use it, it never gets the right activtiy entry.
public void delete(View view){
final int position = listview.getPositionForView((View) view.getParent());
String id = cursor.getString(cursor.getColumnIndex(SQLiteAdapter.KEY_ID));
AlertDialog.Builder myDialog = new AlertDialog.Builder(MainActivity.this);
myDialog.setTitle("Delete activity entry \"" + id + "\"?");
myDialog.setPositiveButton("DELETE", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
mySQLiteAdapter.delete(position);
cursor.requery();
}
});
myDialog.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
}
});
myDialog.show();
}
A solution is to implement a custom ArrayAdapter.
public class MyArrayAdapter extends ArrayAdapter<YourObject>
{
private ArrayList<YourObject> items;
public LiftArrayAdapter(Context context, int textViewResourceId, ArrayList<YourObject> items)
{
super(context, textViewResourceId, items);
this.items = items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
View v = convertView;
if (v == null)
{
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.your_view_xml, null);
}
final YourObject obj = items.get(position);
TextView lblLift = (TextView) v.findViewById(R.id.lbl_lift);
ImageButton btnDelete = (ImageButton) v.findViewById(R.id.btn_delete);
btnDelete .setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
//TODO delete 'obj' from database
}
});
return v;
}
}
Then, to bind a list of objects to your listview:
List<YourObject> list = ...
MyArrayAdapter myArrayAdapter = new MyArrayAdapter (.., .. , list);
listView.setAdapter(myArrayAdapter);

Start activity, stop timer, change values from another class

I don't know neither how to write my question so I hope you will understand from my code:
So i have this EXAMPLE code:
MAIN:
public class ListImageButton extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list);
ListView lv = (ListView) findViewById( R.id.list );
lv.setOnItemClickListener(
new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0,
android.view.View arg1, int arg2, long arg3) {
//HERE THIS IS WORKING
boolean_toast = false;
timer.cancel();
zanimivosti.cancel();
Intent intent = new Intent(ListImageButton.this,
ANOTHER_ACTIVITY.class);
startActivity(intent);
}
});
ArrayList<String> items = new ArrayList<String>();
items.add( "item1");
items.add( "item2");
ListAdapter adapter = new ListAdapter( this, items);
lv.setAdapter( adapter );
}
}
And the ADAPTER:
public class ListAdapter extends BaseAdapter {
public ListAdapter(Context context,
List<String> items ) {
inflater = LayoutInflater.from( context );
this.context = context;
this.items = items;
}
public int getCount() {
return items.size();
}
public Object getItem(int position) {
return items.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
String item = items.get(position);
View v = null;
if( convertView != null )
v = convertView;
else
v = inflater.inflate( R.layout.item, parent, false);
TextView itemTV = (TextView)v.findViewById( R.id.item);
itemTV.setText( item );
ImageButton button =
(ImageButton)v.findViewById( R.id.button);
button.setOnClickListener(
new OnClickListener() {
public void onClick(View v) {
//HERE THIS IS NOT WORKING
boolean_toast = false;
timer.cancel();
zanimivosti.cancel();
Intent intent = new Intent(ListImageButton.this,
ANOTHER_ACTIVITY.class);
startActivity(intent);
}
});
return v;
}
private Context context;
private List<String> items;
private LayoutInflater inflater;
}
So I would like to stop some timers and cancel some toast that I have in the main activity/class, and also I would like to start a new activity.
Ok I thought about it and the answer was very simple..looks like I was to tired to think about it..
I made this function in the main activity:
public static void preklopi() {
boolean_toast = false;
cas = 0;
perioda = 0;
timer.cancel();
zanimivosti.cancel();
Intent intent = new Intent(Context, kasper.api.Najdi_osebo.class);
Context.startActivity(intent);
}
And then I called the function from main activity in the other class..

Add item in listview arrayadapter

Please tell me how to add items in listview arrayadapter?
I found only how to make for standard adapter
Activity:
public class Activity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.m);
ListView lv=(ListView) findViewById(R.id.lv);
String[] Id1={"1","2","3"}, Text1={"one","two","three"};
CustomAdapter ad = new CustomAdapter(this, Id1 , Text1);
ad.setCustomListener(new LVListener() {
public void onClick(String text) {
Log.d("APP", text);
}
});
lv.setAdapter(ad);
Button btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
btn.setVisibility(View.GONE);
String[] Id2={"4","5","6"},Text2={"four","five","six"};
// add Id2 and Text2 in listview
}
});
}
}
CustomAdapter:
public class CustomAdapter extends ArrayAdapter<String> {
private final Context context;
private final String[] id, text;
private ListViewListener micl;
public CustomAdapter(Context context, String[] id, String[] text) {
super(context, R.layout.list, id);
this.context = context;
this.id = id;
this.text = text;
}
public void setCustomListener(ListViewListener micl) { this.micl = micl; }
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View View = inflater.inflate(R.layout.list, parent, false);
final int pos = position;
final TextView tView = (TextView) View.findViewById(R.id.textView);
tView.setText(text[pos]);
rowView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (micl != null)
micl.onClick(text[pos]);
}
});
return View;
}
}
I tried to do with notifyDatasetChanged() but nothing happened.
Please tell me how to do that.
ArrayAdapter has the add method, but in order to use it the dataset you provide to the super can not be an array, that's because the using Arrays.asList(objects), that returns an immutable list. From the documentation
Returns a List of the objects in the specified array. The size of the
List cannot be modified, i.e. adding and removing are unsupported, but
the elements can be set. Setting an element modifies the underlying
array.

Deleting the checked items in the listview

I want to make an app which includes a listView with check boxes and a two buttons named add and delete selected. I want to delete all the item that are checked in the list view.I am unable to do that despite of my lot of efforts. Any help would be appreciated.
Here is my code
package com.example.chkbokinlistview;
public class Adapter extends ArrayAdapter<Movies> {
ArrayList<Movies> data;
Context context;
int id;
private Holder h;
public Adapter(Context context, int textViewResourceId, ArrayList<Movies> objects) {
super(context, textViewResourceId, objects);
this.data = objects;
this.context = context;
this.id = textViewResourceId;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final int p = position;
View v = convertView;
LayoutInflater l = ((Activity)context).getLayoutInflater();
h = new Holder();
if (v == null) {
v = l.inflate(id, parent, false);
h.tv = (TextView) v.findViewById(R.id.textView1);
h.cb = (CheckBox) v.findViewById(R.id.checkBox1);
v.setTag(h);
}else{
h = (Holder) v.getTag();
h.cb.setChecked(true);
}
h.tv.setText(data.get(position).movieName);
h.cb.setChecked(data.get(position).deleted);
return v;
}
public void delete(){
//how to delete all the items that are checked
}
class Holder{
TextView tv;
CheckBox cb;
}
}
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.lv);
bDelete = (Button) findViewById(R.id.bDelete);
bAdd = (Button) findViewById(R.id.bAdd);
list = new ArrayList<Movies>();
a = new Adapter(this, R.layout.listitem, list);
lv.setAdapter(a);
bDelete.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
a.delete();
}
});
bAdd.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
final EditText et = new EditText(MainActivity.this);
dialog = new AlertDialog.Builder(MainActivity.this)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg0, int arg1) {
// TODO Auto-generated method stub
list.add(new Movies(et.getText().toString(), false));
a.notifyDataSetChanged();
dialog.dismiss();
}
})
.setTitle("ADD Movie")
.setView(et)
.create();
dialog.show();
}
});
}
On checking the checkbox add that position in an ArrayList let say toBeDeleted, and when you click delete button, just remove items from your ArrayList named data according to the positions that you have in toBeDeleted and call the adapter method notifyDataSetChanged().
Add a checkedChangedListener in the getView method for your CheckBox.
h.cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton arg0,
boolean arg1) {
// TODO Auto-generated method stub
if (arg1) {
list.add(position);
} else {
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == position) {
list.remove(i);
break;
}
}
}
}
});
Where list is a ArrayList<Integer>,
and for deleting
private void delete() {
for(int i = 0 i<list.size;i++)
data.remove(list.get(i));
}
but before deleting you have to sort the list in decending order, in order to remove correctly, otherwise you may get an IndexOutofBoundException

Categories

Resources