update listview on save - android

I have a code where I add all TODOs to the adapter, like this
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_todo);
adapter = new TODOAdapter(this, TODO.listAll(TODO.class));
listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(adapter);
}
When add I new TODO, I do this
private void createTodo(String s) {
TODOWorker.createTodo(s);
adapter.notifyDataSetChanged();
Toast.makeText(getApplicationContext(), "Your TODO was saved!", Toast.LENGTH_LONG).show();
}
but my listview is not beign updated...what am I missing?

My best guess after looking at your code is before calling notifyDatasetChanged() on your adapter you need to set the new list on the adapter. So when a new TODO is created add it to the list and update the list that the adapter is working with. Then call the notifyDatasetChanged()
So let's say your adapter has a List<TODO> mDataList then you need to have a function like this
public void setData(List<TODO> updatedList) {
mDataList = new ArrayList<>(updatedList);
notifyDataSetChanged();
}
and change your createToDo() to this
private void createToDo(String s) {
TODOWorker.createTodo(s);
adapter.setData(TODO.listAll(TODO.class));
Toast.makeText(getApplicationContext(), "Your TODO was saved!", Toast.LENGTH_LONG).show();
}
Hope this helps. I am assuming of course that your TODOWorker is not updating the list that the adapter is working with.

When you create Adapter, it is backed by List, which you create by TODO.listAll(TODO.class)
You have to make sure that new item is inserted into this List before adapter.notifyDataSetChanged() called.

Related

List can't be saved or loaded

I tried making a dynamic list where the user can add elements by writing a text and pushing a button. The user also should be able to delete elements by clicking on them for a longer time.
All of that is working fine, however everytime I close the App the created list is gone. I'm not sure what exactly is failing, either the loading or the saving.
Here is my code:
public class MainActivity extends AppCompatActivity {
private ArrayList<String> ModuleList;
private ArrayAdapter<String> MyAdapter;
private ListView listView;
private Button addButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadData();
addButton=findViewById(R.id.btnPlus);
MyAdapter=new ArrayAdapter<>(this, android.R.layout.simple_list_item_1);
listView=findViewById(R.id.listView);
listView.setAdapter(MyAdapter);
addButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
addModule(view);
saveData();
}
});
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener()
{
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id)
{
deleteItem(view, position);
saveData();
return true;
}
});
}
private void addModule(View view) {
EditText input =findViewById(R.id.textInput);
String itemText=input.getText().toString();
if(!(itemText.equals("")))
{
ModuleList.add(itemText);
MyAdapter.add(itemText);
MyAdapter.notifyDataSetChanged();
input.setText("");
}
else
{
Toast.makeText(getApplicationContext(),"Please insert Module...",Toast.LENGTH_LONG).show();
}
}
private void deleteItem(View view,int i)
{
Context context = getApplicationContext();
MyAdapter.remove(ModuleList.get(i));
ModuleList.remove(i);
MyAdapter.notifyDataSetChanged();
Toast.makeText(context, "Item Removed", Toast.LENGTH_LONG).show();
}
private void saveData()
{
SharedPreferences sharedPreferences=getSharedPreferences("Shared preferences",MODE_PRIVATE);
SharedPreferences.Editor editor=sharedPreferences.edit();
Gson gson=new Gson();
String json=gson.toJson(ModuleList);
editor.putString("Task List",json);
editor.apply();
}
private void loadData()
{
SharedPreferences sharedPreferences=getSharedPreferences("Shared preferences",MODE_PRIVATE);
Gson gson=new Gson();
String json=sharedPreferences.getString("Task List",null);
Type type= new TypeToken<ArrayList<String>>() {}.getType();
ModuleList=gson.fromJson(json,type);
if(ModuleList==null){
ModuleList=new ArrayList<>();
}
}
}
I can't see my mistake, but I'm new to all of this. So there might be something obvious missing.
Thank you very much.
i once encountered the same problem and the solution was
instead of
SharedPreferences sharedPreferences=getSharedPreferences("Shared preferences",MODE_PRIVATE);
write (remove the space from the name)
SharedPreferences sharedPreferences=getSharedPreferences("Sharedpreferences",MODE_PRIVATE);
similarly with your variable name
editor.putString("TaskList",json);
String json=sharedPreferences.getString("TaskList",null);
i don't know if this is your case or why this happens since the variable is a string and the space shouldn't matter but for me it never allows me to save anything in sharedPrefs if the name has spaces
then check this line
MyAdapter=new ArrayAdapter<>(this, android.R.layout.simple_list_item_1);
update it with this
MyAdapter=new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,ModuleList);
for the issue in saving the item twice the problem is here
if(!(itemText.equals("")))
{
ModuleList.add(itemText);
// MyAdapter.add(itemText); remove this line the itemText is already added to the moduleList
MyAdapter.notifyDataSetChanged();
input.setText("");
}
First: create a static final variable to store "Task List", then add some Log.d("TEST", variable) to show in 'Logcat' the interested variables and then update the question please.

What is the difference between listViewAdapter.clear() and list.clear()?

Okay, I think I have understood it, but I just want to make sure of it. I have got a ListViewAdapter that contains a List.What I wanna do is search thinks in the database and show in a ListView. This piece of code adds an item to my listView.
list.addAll(sqh.DisplayRecords(sqdb));
listViewAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,list);
listview.setAdapter(listViewAdapter);
search.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
listViewAdapter.clear();
list.clear();
list.addAll(sqh.DisplayRecords(sqdb));
list.add("another one");
}
});
Whit this other piece of code, only clearing the listviewAdapter and adding another item to the list, just, adds the last item, instead of all the items of the list, which should be there.
list.addAll(sqh.DisplayRecords(sqdb));
listViewAdapter = new ArrayAdapter( this,android.R.layout.simple_list_item_1,list);
listview.setAdapter(listViewAdapter);
search.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
listViewAdapter.clear();
list.add("another one");
}
});
Well, I think I understood it while I was writing this. The third one and the first one are pretty the same.
list.addAll(sqh.DisplayRecords(sqdb));
listViewAdapter = new ArrayAdapter( this,android.R.layout.simple_list_item_1,list);
listview.setAdapter(listViewAdapter);
search.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
listViewAdapter.clear();
list.addAll(sqh.DisplayRecords(sqdb));
list.add("another one");
}
});
The listViewAdapter.clear(); would be clearing the list of the adapter, right? Why, when I do just list.clear(), the list view is not cleared?
When you calling list.clear();, you'are removing all of the elements from the list. The list will be empty after this call returns. But your Adapter view isn't change yet. You need to call adapter.notifyDataSetChanged() to refresh the adapter.
In the other case, when you calling listViewAdapter.clear();, the list will be cleared first then the notifyDataSetChanged() called.
You can see the details in ArrayAdapter.clear() source code:
/**
* Remove all elements from the list.
*/
public void clear() {
synchronized (mLock) {
if (mOriginalValues != null) {
mOriginalValues.clear();
} else {
mObjects.clear();
}
mObjectsFromResources = false;
}
if (mNotifyOnChange) notifyDataSetChanged();
}
listViewAdapter.clear()
void clear ()
Remove all elements from the list.
And list.clear();
/**
* Removes all of the elements from this list. The list will
* be empty after this call returns.
*/
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
If you use in this , it was the same .It used to Removes all of the elements from this list .

ListFragment's setListShown method not working

I'm using ListFragment with ParseQueryAdapter in order to show list of leagues (custom model).
I managed to get my desired state except that the loading animation is not showing at all.
It seems like the animation is hidden when the listsAdapter is set (by setListAdapter method), so I set the adapter only after my list is fetched, but the parseQueryAdapter fetches the list only after setting the adapter to a list.
So I found that I can use the setListShown method in order to hide/show the animation, but in my current implementation it doesn't work.
My code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
// Create query factory
ParseQueryAdapter.QueryFactory<League> factory = new ParseQueryAdapter.QueryFactory<League>() {
public ParseQuery<League> create() {
ParseQuery<League> query = League.getQuery();
query.whereEqualTo(League.FIELD_USER, ParseUser.getCurrentUser());
query.orderByDescending(League.FIELD_CREATED_AT);
return query;
}
};
// Create adapter
leagueListAdapter = new LeagueAdapter(getActivity(), factory);
// Loading listener
leagueListAdapter.addOnQueryLoadListener(new ParseQueryAdapter.OnQueryLoadListener<League>() {
#Override
public void onLoading() {
// Show ListFragment's loading animation while loading
setListShown(false);
}
#Override
public void onLoaded(List<League> leagues, Exception e) {
if(e == null){
// Hide loading animation and show the list
setListShown(true);
// Put leagues in the cache
LeaguesCache.getInstance().setCachedLeagues(leagues);
} else {
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
}
}
});
// Set fragment's adapter
setListAdapter(leagueListAdapter);
// Dialogs
addLeagueDialog = new addLeagueDialog(this);
}

AutoCompleteTextView not showing any drop down items

My XML:
<AutoCompleteTextView
android:id="#+id/searchAutoCompleteTextView_feed"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:completionThreshold="2"
android:hint="#string/search" />
MY java code:
AutoCompleteTextView eT = (AutoCompleteTextView)findViewById(R.id.searchAutoCompleteTextView_feed);
eT.addTextChangedListener(this);
String[] sa = new String[]{"apple", "mango", "banana", "apple mango", "mango banana"};
ArrayAdapter<String> aAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line, sa);
eT.setAdapter(aAdapter);
This is not working atall....i mean its just working like an EditTextView. Where am i wrong??
complete code:
public class FeedListViewActivity extends ListActivity implements TextWatcher{
private AutoCompleteTextView eT;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.feed);
eT = (AutoCompleteTextView) findViewById(R.id.searchAutoCompleteTextView_feed);
eT.addTextChangedListener(this);
Thread thread = new Thread(null, loadMoreListItems);
thread.start();
}
private Runnable returnRes = new Runnable() {
public void run() {
//code for other purposes
}
};
private Runnable loadMoreListItems = new Runnable() {
public void run() {
getProductNames();
// Done! now continue on the UI thread
runOnUiThread(returnRes);
}
};
protected void getProductNames() {
String[] sa = new String[]{"apple", "mango", "banana", "apple mango", "mango banana"};
ArrayAdapter<String> aAdapter = new ArrayAdapter<String>(getApplicationContext(),
android.R.layout.simple_dropdown_item_1line, sa);
eT.setAdapter(aAdapter);
}
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
}
}
I just saw your other question before seeing this one. I was struggling with autocomplete for some time and I almost reverted to your new implementation of downloading all the keywords until I finally got it to work. What I did was;
//In the onCreate
//The suggestArray is just a static array with a few keywords
this.suggestAdapter = new ArrayAdapter<String>(this, this.suggestionsView, suggestArray);
//The setNotifyOnChange informs all views attached to the adapter to update themselves
//if the adapter is changed
this.suggestAdapter.setNotifyOnChange(true);
In my textwatcher's onTextChanged method, I get the suggests using an asynctask
//suggestsThread is an AsyncTask object
suggestsThread.cancel(true);
suggestsThread = new WertAgentThread();
suggestsThread.execute(s.toString());
In the AsyncTask's onPostExecute I then update the autocompletetextview
//suggestions is the result of the http request with the suggestions
this.suggestAdapter = new ArrayAdapter<String>(this, R.layout.suggestions, suggestions);
this.suggestions.setAdapter(this.suggestAdapter);
//notifydatasetchanged forces the dropdown to be shown.
this.suggestAdapter.notifyDataSetChanged();
See setNotifyOnChange and notifyDataSetChanged for more information
this is a snippet from my project. I think after you got data from services all you have to do is to:
clear your previous data.
clear the previous adapter values.
then add values to your list of data using add() or addAll() method.
notify the data changed by calling notifyDataSetChanged() on adapter.
#Override
public void onGetPatient(List<PatientSearchModel> patientSearchModelList) {
//here we got the raw data traverse it to get the filtered names data for the suggestions
stringArrayListPatients.clear();
stringArrayAdapterPatient.clear();
for (PatientSearchModel patientSearchModel:patientSearchModelList){
if (patientSearchModel.getFullName()!=null){
stringArrayListPatients.add(patientSearchModel.getFullName());
}
}
//update the array adapter for patient search
stringArrayAdapterPatient.addAll(stringArrayListPatients);
stringArrayAdapterPatient.notifyDataSetChanged();
}
but before all this make sure you have attached the adapter to the auto complete textview if don't do it as follows:
ArrayAdapter<String> stringArrayAdapterPatient= new ArrayAdapter<String>(getActivity(),android.support.v7.appcompat.R.layout.select_dialog_item_material,stringArrayListPatients);
completeTextViewPatient.setAdapter(stringArrayAdapterPatient);
Use adapter.notifyDataSetChanged() method to notify the changes in the list, If that is not working then you can show DropDown manually like autoCompleteTextView.showDropDown()
AutoCompleteTextView eT = (AutoCompleteTextView)findViewById(R.id.searchAutoCompleteTextView_feed);
// eT.addTextChangedListener(this);
String[] sa = new String[]{"apple", "mango", "banana", "apple mango", "mango banana"};
ArrayAdapter<String> aAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line, sa);
eT.setAdapter(aAdapter);
its working just comment on et.addtext line...
The only working solution after updating adapter and notifying about changes instantly show dropDown is reseting AutoCompleteTextView text again, Kotlin example:
with(autoCompleteTextView) {
text = text
// Place cursor to end
}
Java something like:
autoCompleteTextView.setText(autoCompleteTextView.getText());
// Place cursor to end
AutoCompleteTextView.Invalidate()
will do it.
If anyone is using a custom object array list, and facing this issue, check your model class and see if you have override the correct variable in toString. Overriede toString if you have not override yet.
public class MyModalClass {
public int id;
public String path;
#Override
public String toString() { //include this in your model and return what you need in your drop down
return path;
}
}

How to create a layout like Android CallLog's layout

Hey I want to create a layout like this for my application. Of course the functionalities will be differents. I'm studying the source code for this, and I found the xml files that does that. I just dont know how to implement that in the activity, how to call, what to create, a listview, etc.
I mean, I just want to list the name with a bigger font and the date like in the image, with a small font but aligned to the right.
Because, I want to get the data from the database I've created and print it like this list of CallLog.
I mean, how Android makes the date with that icon align in the right, with a small font size?
So this is my activity, I just dont know what xml file from the source code to use, or what method to implement so I can print the data like the image example.
public class RatedCalls extends ListActivity {
private static final String LOG_TAG = "RatedCalls";
private TableLayout table;
private CallDataHelper cdh;
private TableRow row;
private TableRow row2;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recent_calls);
Log.i(LOG_TAG, "calling from onCreate()");
cdh = new CallDataHelper(this);
startService(new Intent(this, RatedCallsService.class));
Log.i(LOG_TAG, "Service called.");
Log.i(LOG_TAG, "before call fillList");
/*
* mAdapter = new RecentCallsAdapter();
* getListView().setOnCreateContextMenuListener(this);
* setListAdapter(mAdapter);
*/
fillList();
Log.i(LOG_TAG, "after call fillList");
}
public void onResume() {
super.onResume();
fillList();
}
public void fillList() {
Log.i(LOG_TAG, "entered on fillList");
List<String> ratedCalls = new ArrayList<String>();
ratedCalls = this.cdh.selectTopCalls();
//setListAdapter(new ArrayAdapter<String>(this, R.layout.recent_calls_list_item,
//ratedCalls));
ListView lv = getListView();
lv.setTextFilterEnabled(true);
getListView().setOnCreateContextMenuListener(this);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(getApplicationContext(),
((TextView) view).getText(), Toast.LENGTH_LONG).show();
}
});
}
}
Thanks.
It's just a 2 step process:
Create a Layout Xml file which represents 1 item of your list.
Extend Array Adapter and use your custom layout file there. There are several examples on the internet on how to extend Array Adapter.
I'm going to create a listview with multiple textviews.

Categories

Resources