I created an app that it should work as a telephone directory. Firstly I enter the data, then save, and finally I should see a list (listView) with my saved data.
But I don't see no list, although the data are present in the database. I inserted an "else" statement for to control if the db is full.
MainActivity.java
if(gridList.size()!=0){
Log.i("PROVA", "size: " + gridList.size());
ListView listView = getListView();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
id_grid = (TextView) view.findViewById(R.id.id_grid);
String id_gridValue = id_grid.getText().toString();
Intent theIntent = new Intent(getApplication(),EditSheet.class);
theIntent.putExtra("id_grid", id_gridValue);
startActivity(theIntent);
ListAdapter adapter = new SimpleAdapter(MainActivity.this,gridList, R.layout.grid_entry, new String[]{
"id_grid", "site"}, new int[] {R.id.id_grid, R.id.edit_site});
/*String[] values = new String[]{"id_grid", "edit_site", "edit_tab"};
ArrayAdapter adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1,
values);*/
setListAdapter(adapter);
}
});
} else {
Log.i("PROVA", "size = 0");
}
and the result is this:
[
I/PROVA: size: 1
W/EGL_emulation: eglSurfaceAttrib not implemented
W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0x7fa218cf5a00, error=EGL_SUCCESS
D/OpenGLRenderer: endAllStagingAnimators on 0x7fa218e4dc00 (RippleDrawable) with handle 0x7fa21bc653a0
Application terminated.
This is the layout of the activity_main:
I believe it's a list display issue.
try to use
listView.notifyDataSetChanged();
Related
Classic problem here: I'm fetching some data from a database into a recyclerView using an ArrayList of custom objects (and this happens in a Fragment, not in the Main Activity). Everything works like a charm until I try to refresh the recyclerView using a spinner that changes how the data is sorted. I know the data is fed to the recyclerView correctly. What am I doing wrong? API level is 19.
This is how the fetch is done:
public ArrayList<LEGOSet> getSets(String conditions) {
ArrayList<LEGOSet> sets = new ArrayList<>();
Cursor cursor = database.rawQuery("SELECT * FROM Sets " + conditions, null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
LEGOSet set = new LEGOSet(cursor.getInt(0), cursor.getString(1), cursor.getInt(2), cursor.getInt(3), cursor.getString(4), cursor.getDouble(5),
cursor.getDouble(6), cursor.getDouble(7), cursor.getDouble(8), cursor.getDouble(9), cursor.getDouble(10), cursor.getString(11),
cursor.getString(12), cursor.getString(13), cursor.getString(14), cursor.getInt(15), cursor.getInt(16), cursor.getInt(17));
sets.add(set);
cursor.moveToNext();
}
cursor.close();
return sets;
}
The fragment with the data being pulled, the recyclerView being set up and with the spinner onItemSelected code:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_catalog, container, false);
// pull data from database
sets = dbManager.getSets("order by pieces desc");
// set up the RecyclerView
final RecyclerView recyclerView = root.findViewById(R.id.rvSets);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
adapter = new MyRecyclerViewAdapter(getActivity(), sets, portrait);
adapter.setClickListener(this);
recyclerView.setAdapter(adapter);
// add dividers
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), 1);
dividerItemDecoration.setDrawable(new ColorDrawable(getResources().getColor(R.color.colorSubtle)));
recyclerView.addItemDecoration(dividerItemDecoration);
// spinner Product Sorting
spinnerProductSorting = root.findViewById(R.id.spinnerProductSorting);
spinnerProductSorting.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
String s = spinnerProductSorting.getSelectedItem().toString();
switch(s)
{
case "Biggest first":
sets = dbManager.getSets("order by pieces desc");
Toast.makeText(getContext(),sets.get(0).getName(), Toast.LENGTH_SHORT).show();
break;
case "Smallest first":
sets = dbManager.getSets("order by pieces asc");
Toast.makeText(getContext(),sets.get(0).getName(), Toast.LENGTH_SHORT).show();
break;
default:
}
adapter.notifyDataSetChanged();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {}
});
disclaimer = root.findViewById(R.id.disclaimer);
disclaimer.setMovementMethod(LinkMovementMethod.getInstance());
return root;
}
What I've noticed is that I can get refreshed recyclerView if I replace:
adapter.notifyDataSetChanged();
with
adapter = new MyRecyclerViewAdapter(getActivity(), sets, portrait);
recyclerView.setAdapter(adapter);
But that doesn't seem right. I should be able to refresh the existing adapter with new data instead of creating a brand new adapter, correct?
This is a classic issue faced by many developers frequently.
Quick Fix:
Replace
sets = dbManager.getSets("order by pieces desc");
with
sets.clear()
sets.addAll(dbManager.getSets("order by pieces desc"));
And same for Ascending Order also.
Explanation:
When you initialize the Adapter, you pass an Arraylist whose instance is stored by the Adapter. When you call notifyDataSetChanged(), Adapter reads the instance and refreshes the layout as per the new ArrayList. However, when you reinitialize the ArrayList with sets = dbManager.getSets("order by pieces desc");, the adapter loses the reference to the new list and is unable to refresh the layout. This can be fixed by keeping the instance the same and replacing the values which are done using clear() and addAll(list).
Feel free to ask for any doubts in comments and please mark this answer correct if I am able to solve your problem.
Inside your adapter class create method:
setData(ArrayList<LEGOSet> sets) { // new list here
this.sets = sets; // assing ArrayList from database to your list which is inside adapter class
notifyDataSetChanged();
}
and then just replace adapter.notifyDataSetChanged() with adapter.setData(sets)
Visual Reference
EDITED WITH COMMENT FIX
My listView is supposed to, on long tap, delete whatever you tap on. There is data in sharePreferences, so that shouldn't be the problem. So, what I am doing is I am taking data from noteSet, which gets it from myPref. Then, where the listView gets clicked, the notesSet deletes that note. Then, it reuploads the modified notesSet to sharedPreferences and then notesSet is added to notes, which is used by the listview.
I think this is the error code I am getting:
02-23 12:20:12.384 5211-5229/com.example.jackson.collegeplanner E/OpenGLRenderer: GL error: GL_INVALID_OPERATION
02-23 12:20:28.461 550-710/system_process W/InputDispatcher: channel '17b2c24b com.example.jackson.collegeplanner/com.example.jackson.collegeplanner.Schedule (server)' ~ Consumer closed input channel or an error occurred. events=0x9
02-23 12:22:12.723 54-54/? E/EGL_emulation: tid 54: eglCreateSyncKHR(1299): error 0x3004 (EGL_BAD_ATTRIBUTE)
myPref.edit().putStringSet("NN", notesSet).apply();
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
new AlertDialog.Builder(getApplicationContext()).setIcon(android.R.drawable.ic_dialog_alert).setTitle("Pop Up!")
.setMessage("Ready to delete this task?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
SharedPreferences myPref = getApplicationContext().getSharedPreferences("com.example.jackson.collegeplanner", Context.MODE_PRIVATE);
Set<String> notesSet = new HashSet<String>(myPref.getStringSet("NN", null));
ArrayAdapter arrayAdapter = new ArrayAdapter(getApplicationContext(), android.R.layout.simple_list_item_1, notes);
ListView listView = (ListView) findViewById(R.id.listView);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
notesSet.remove(i);
notes.clear();
notes.addAll(notesSet);
myPref.edit().putStringSet("NN", notesSet).apply();
listView.setAdapter(arrayAdapter);
Log.i("TEST", "notesSet didn't return null!");
}
})
.setNegativeButton("No", null).show();
return false;
}
});
This is a snippet of code from my program for convienence. The rest of the program works, and app crashes only occur when I introduced this new code. Thanks for your time.
Use Acivity's context instead of getApplicationContext() . Do not use getApplicationContext() anywhere unless it meant to be use . Do it as below .
new AlertDialog.Builder(YourActtivity.this).setIcon(android.R.drawable.ic_dialog_alert).setTitle("Pop Up!")
.setMessage("Ready to delete this task?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
SharedPreferences myPref = getSharedPreferences("com.example.jackson.collegeplanner", Context.MODE_PRIVATE);
Set<String> notesSet = new HashSet<String>(myPref.getStringSet("NN", null));
ListView listView = (ListView) findViewById(R.id.listView);
notesSet.remove(i);
notes.clear();
notes.addAll(notesSet);
myPref.edit().putStringSet("NN", notesSet).apply();
ArrayAdapter arrayAdapter = new ArrayAdapter(YourActtivity.this, android.R.layout.simple_list_item_1, notes);
listView.setAdapter(arrayAdapter);
Log.i("TEST", "notesSet didn't return null!");
}
})
.show();
Also Debug your code check and for returned values .
I'm trying to get the position of an array using the onItemClickListner.
With the following code, I am able to pass the text of the item clicked but not the position of the array eg 0, 1, 2 etc.
String[] menuItems = new String[]{"Hello", "Is it me", "Youre", "Looking for"};
ListAdapter adapter = new ArrayAdapter<String>(this, R.layout.menulists, R.id.menulistsTextView1, menuItems);
ListView listView = (ListView) findViewById(R.id.mainListView1);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> l, View v, int position, long id) {
String selected = (String) l.getItemAtPosition(position);
}
Any tips on whether it is possible to do that, I tried changing String to int and also to use the getItemIDAtPosition function but would not work, would just close the application.
Cheers
EDIT
I have just taken a different approach to achieving what I want to do using if statements for the string of the item clicked. Thanks for the input
You can get the position from method signature :
public void onItemClick(AdapterView<?> l, View v, int position, long id)
position give you index of selected item.
you may try this :
String itemClicked = menuItems[position];
As I understand Your problem - You want to get item on clicked position. Do do so use getItem(position) method of adapter. Code:
String[] menuItems = new String[]{"Hello", "Is it me", "Youre", "Looking for"};
//VERY IMPORTANT
//adapter must be declared final to use it in onItemClick
//or adapter should be object parameter
final ListAdapter adapter = new ArrayAdapter<String>(this, R.layout.menulists, R.id.menulistsTextView1, menuItems);
ListView listView = (ListView) findViewById(R.id.mainListView1);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> l, View v, int position, long id) {
String selected = <String>adapter.getItem(position);
}
});
I can't find an answer to delete in a listview created using SimpleCursorAdapter
So i make this listview in a fragment, here's the code
final Cursor cursor = myDb.cautarevenituri();
// The desired columns to be bound
final String[] columns = new String[] {
DatabaseHelper.COL_2,
DatabaseHelper.COL_3
};
int[] toviewids = new int[] { R.id.nume_item,R.id.valoare_item};
dataAdapter = new SimpleCursorAdapter(getActivity().getBaseContext(),R.layout.item_layout,cursor,columns,toviewids,0);
//
final ListView listView = (ListView)getView().findViewById(R.id.listView_venituri);
listView.setAdapter(dataAdapter);
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long arg3) {
Toast.makeText(getActivity(), " " + position, Toast.LENGTH_LONG).show();
//delete from listview in database and listview too??
//
//
return false;
}
});
Thank you.
Delete from Database and refresh the listview.
You have to update your list that you passed into the adapter and then call adapter.notifyDataSetChanged()
Use the swapCursor() method to update the data inside a SimpleCursorAdapter:
myDb.getWriteableDatabase().delete(TABLE_NAME, KEY_ID + "=?", position);
Cursor newCursor = myDb.getReadableDatabase().query(**etc.**);
dataAdapter.swapCursor(newCursor);
I have created an AutoCompleteTextView drop-down which contains multiple words in a row like -
row 1 - Infosys Limited
row 2 - State Bank of India
when I'm entering Infosys, it works fine when I enter space after the drop-down goes off.
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, GreenDaoUtils.getSSSymbolNamesArray(this));
autoCompleteTextView.setAdapter(adapter);
autoCompleteTextView.setLines(8);
autoCompleteTextView.setDropDownBackgroundDrawable(getResources().getDrawable(R.drawable.cust_rect_border));
autoCompleteTextView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(final AdapterView<?> parent, final View view, final int position, long id) {
});
}
});
Use FilterWithSpaceAdapter instead of ArrayAdapter
u get from FilterWithSpaceAdapter here
FilterWithSpaceAdapter<String> adapter1;
adapter1 = new FilterWithSpaceAdapter<String>(this, android.R.layout.simple_list_item_1, GreenDaoUtils.getSSSymbolNamesArray(this));