SpinnerButtonAdapter using ASyncTask to auto select from database - android

I have a spinner which is populated from the database. This in turn is pulled from a webservice so it is not possible to hard-code the values.
The spinner is part of a form that the user fills out and saves and I need them to be able to go back in and edit the values, so I am trying to auto-populate it based on what was selected.
The problem is that the spinner does not always select, which happens more often than not. I think this is due to the fact that I am loading the data asynchronously using an asynctask, and by the time it retrieves the data the spinner has yet not been loaded. I have logging showing that, for example, spinner item 4 was pulled from the database, but the spinner shows nothing selected.
What is the best way to find out when the loader has been completed so that I can populate (ie select) the relevant item in the list?

I put the call at the end of the load finished method,
#Override
public void onLoadFinished(Loader<Cursor> aLoader, Cursor aCursor) {
int id = aLoader.getId();
Loader<Cursor> cursorLoader = null;
switch (id) {
mAdapter.swapCursor(aCursor);
}
if (inEditMode) {
fillInValues();
}
}

Related

Android ListView with “tabs”

picture from a reddit news feed
(https://i.stack.imgur.com/6YXMK.jpg)
I am creating an app with a list view that is populated from a sqlite database. Each of the data base items can have a status of either “resolved” or “unresolved”.
I want the listview to have 3 “tabs” with the labels “all items”, “resolved items”, and “unresolved items” with correspoding sqlite queries to populate each.
It should behave similarly to the one pictured.
I assumed this would be a tabbed listview and have been watching tutorials for a week based on those search words and it’s taking taking me down a dark rabbit hole of fragments and changing gradles and so on. I’m not sure tabs are what i really want.
Could I do this with three buttons instead where each button would run a different query and populate my listviewcontainer?
Ideally, when the page is opened, the first “tab” would be highlighted and the listview populated with all records. As the other tabs are pressed, they would highlight and a new query would run.
Would another approach work better?
I’m not asking for code, I just want some conceptual direction on where to focus my research.
If I get you right you need to filter your query results in different lists. Making a lot of queries into database is not the thing that is preferable specially if it's going to be a long process and doing it a lot of times is time and memory consuming.
So to make it work you could simple store your full query result in one variable and change the RecyclerView data using custom method setList() and later using notifyDataSetChanged() to apply the changes.
To make it work you need to get understanding of "how RecyclerView works" and then you will be fine.
So after providing the right logic you would be able to simple split your whole query result as it's needed (by element values for example) as it's showed above:
About the code below:
list - is your query result
leftFilterList or rightFilterList - are lists that contain sorted items
adapter.setList(rightFilterList) - sets the RecyclerView data (filtered items in our case)
adapter.notifyDataSetChanged() - is used to notify RecyclerView that list was changed, and he need to rebuild it.
So we have two Buttons and logic that fillter items in differend ways.
public void left(View view) {
ArrayList<ExampleItem> leftFilterList = new ArrayList<>();
for (ExampleItem item : list) {
if (item.getTitle().length() % 2 == 0) {
leftFilterList.add(item);
}
}
adapter.setList(leftFilterList);
adapter.notifyDataSetChanged();
}
public void right(View view) {
ArrayList<ExampleItem> rightFilterList = new ArrayList<>();
for (ExampleItem item : list) {
if (item.getTitle().length() % 2 == 1) {
rightFilterList.add(item);
}
}
adapter.setList(rightFilterList);
adapter.notifyDataSetChanged();
}
And the result of filtering*:
sorry for wrong toast text. It shows the whole list size.

Couchbase lite on Android, retrieve views

This question is about Couchbase lite (no Sync Gateway).
I'm new to Couchbase, I managed to use the demo app, but I don't understand it completely.
It contains this code which (as far as I understand, since I'm not native English speaker) retrieve views to populate a listview with the indexes:
// This code can be found in ListsActivity.java
// in the setupViewAndQuery() method
com.couchbase.lite.View listsView = mDatabase.getView("list/listsByName");
if (listsView.getMap() == null) {
listsView.setMap(new Mapper() {
#Override
public void map(Map<String, Object> document, Emitter emitter) {
String type = (String) document.get("type");
if ("task-list".equals(type)) {
emitter.emit(document.get("name"), null);
}
}
}, "1.0");
}
listsLiveQuery = listsView.createQuery().toLiveQuery();
Could anyone give me a hand with what each part is doing?
In which step is the listview populated
Can I change "list/listsByName" in the code (line 3)? What would happen?
Can I emit more than one element?
The code is a little bit convoluted. Let's answer the easy parts first.
Can I change "list/listsByName" in the code (line 3)?
Yes. That's just the name of the Couchbase View. You choose the View name. Unfortunately the terms used in Couchbase and Android overlap some. A Couchbase View is a kind of static index of your database.
Can I emit more than one element?
Yes. You can emit most anything you want. Take a look at the documentation here
Now, tracing how the Android ListView gets updated:
In ListsActivity.java notice in the onCreate method a ListAdapter instance gets added to the ListView. This ListAdapter is a private inner class that extends LiveQueryAdapter.
LiveQueryAdapter is in the utils subpackage. If you look at its constructor, you'll see it adds a change listener to the query passed in. When triggered, this change listener sets an enumerator equal to the rows passed back by the live query, then calls notifyDataSetChanged to tell the list to refresh itself. That, in turn, causes getView in ListAdapter to get called. That's where the data is pulled from the database and used to populate a list entry.

Update or Refresh UI with the update of database android

I have an image gallery. I have to show images with uploaded or not uploaded icon. A service is running in the background to upload the images and update the database.Suppose i am in gallery screen and some not uploaded images has been uploaded and update database. So i want to update my view without press any button.
whenever database is getting updated, is there any way i can get callback ??
what is the best approach to update my view without reload all??
You will need to use CursorLoaders/CursorAdapters. You can find an example here
https://github.com/ksarmalkar/ContentProviderJoin
Two possible ways to update the UI would be:
NotifyDatasetChanged() method which can be used if you are using an adapter to display the images (I would assume you are using an adapter for your gallery). You can call this method each time an upload completes which would then tell the view to update itself.
Otherwise maybe run an AsyncTask which checks the status of the upload every so often and in the onProgressUpdate() method have a callback to your UI thread to update that the image has been uploaded.
I hope this helps.
You can use loader for this.
Loaders have these characteristics:
They are available to every Activity and Fragment.
They provide asynchronous loading of data.
They monitor the source of their data and deliver new results when the content changes.
They automatically reconnect to the last loader's cursor when being recreated after a configuration change. Thus, they don't need to re-query their data.
Find here a get started help.
So :
First you should init you loader like this:
getLoaderManager().initLoader([YOUR_LOADER_ID], null, this);
Define loading instruction in onCreateLoader() :
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// You can return other type than cursor or create your own custom cursorloader but I guess that cursor is right fro you since you want load database content.
Uri baseUri = [you media uri , suppose that you sue content provider];
return new CursorLoader(getActivity(), baseUri,
[projection], [select], [arg],
[orderby]);
}
You get onLoadFinished() callback when data finishes to be loaded :
public void onLoadFinished(Loader loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
mAdapter.swapCursor(data);
}
In your case, loader monitors every change in gallery database. So everytime there is a change, swap cursor is called automatically, then your view is updated according what you defined in your adapter.

greendao listview all data from Entity

GreenDAO.
Which there is a simple way to display all the records from a Entity in the ListView, and is supported with the auto-update the list.
Perhaps Lazylist class? how to use it?
Have a look here. I'm using an adapter like this (including a ViewHolder-Pattern to reuse the Views inside the ListView) as well and it is fast even for a lot of records. But this won't be usable if you need auto-update-functionality.
Here are some information about LasyList to explain why:
Get LazyList using Query.listLazy():
This will not show new inserted records (or stop deleted records from displaying) automatically, since the records are cached in memory.
Thus updates won't be visible, because records are not queried twice.
Get LazyList using Query.listLazyUncached():
Updates of already existing records may be visible, but only if the records updated are currently not displayed.
Also you should be careful because I think inserting or deleting records may break this list.
To get inserts and deletes into the list you will have to refresh the underlying LazyList and call notifyDataSetChanged().
I'm using this in my Adapter:
public void setLazyList(LazyList<T> list) {
if (list != lazyList) {
lazyList.close();
lazyList = list;
this.dataValid = lazyList != null;
notifyDataSetChanged();
}
}
By the way: If you are using LazyList:
Don't forget to close LazyLists if you are not using them any more!

Refreshing a Spinner

I have a view with a spinner. The activity starts another acvitity with a popup where I add or delete values that the parent shows in the Spinner.
So, in onActivityResult() I refresh the content of the Spinner so that it reflects any additional or deleted values, by calling my fillSpinner() method.
The parameter to this method is the previously selected value:
private void fillSpinner(String value){
Cursor c = mDbHelper.getAllCategories();
startManagingCursor(c);
c.moveToFirst();
String[] from = new String[]{DBAdapter.KEY_CATEGORY};
SimpleCursorAdapter scCats = new SimpleCursorAdapter(
this, android.R.layout.simple_spinner_item,c,from,
new int[]{android.R.id.text1});
scCats.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
category.setAdapter(scCats);
if (value != null && value != "") {
category.setSelection((int)mDbHelper.categoryIndex(value));
}
}
When I open the Spinner, it contains the correct list (i.e. it was refreshed) and the correct value is selected. However, the Spinner control itself (in its closed state) does not show the selected value, but the first in the list.
When I step through the code in the debugger, the Spinner value is correct before and after I call setSelection() (and it is always called with the same correct id). However, since I cannot step out of the event, when I resume the execution after a short moment the value in the Spinner changes.
In other words, the spinner's displayed string is changed and is different from the selected item when I return from my popup activity.
Any ideas are appreciated.
I found a simple solution to that problem: Use the form Spinner.setSelection(int position, Boolean NavigateTo) to have the Spinner show the correct selected item.
Example: Spin.setSelection(iPos, true);
Good luck.
The problem, I think, was due to my cursor being recreated on every call. I don't have a better explanation. This post indirectly pointed me in the right direction.
By holding on to the cursor after creating it initially, I was able to just call requery() after changing the list data, as opposed to running through the method in my question. It works fine now.

Categories

Resources