Downloading and parsing JSON files to update ArrayAdapters on demand - java

Well I have an app set up, In way that there are, let's say, 3 ListViews in three different fragments.
Now a server provides 3 JSON files, that contain information, one for each ListView, which I have to parse into objects or lists of objects, and use them to instantiate my custom ArrayAdapters to display information on the list views.
The problem is that Downloading and parsing are operations that should happen outside the GUI thread.
So I am looking for the most effective way to update these list views on demand (when a fragment is inflated or OnResume etc)
What I've tried already was to download the needed json file using an IntentService then send the downloaded buffer to the GUI thread using a ResponseHandler and Intents, and then passing that to a manager class that was responsible for parsing the buffers into objects and populating the views. To do that, I had to keep the Views and the ArrayAdapters as properties to that class and provide on demand update methods.
Now my questions are:
1) Is it possible to have the service download the JSON files, parse them into collections and somehow send ArrayList objects to the GUI thread?
2) If I have to keep the adapters and update them in the GUI thread, what is the most effective (and maybe elegant way) to have a manager class keep and update the ListViews and their ArrayAdapters easily?(Do I have to get a new instance of the ArrayAdapter each time the information is updated, or can I update the inner ArrayList only?)
I think I won't include any code, since this is about the project structure and the preferred ways to do things.If it's needed for some parts though I can always edit the question later.

Related

Making UI elements dynamically in android apps in android studio using java

I am wondering if it is possible to create UI elements dynamically in android apps without using xml or design? The number of elements and type of elements will be different based on the requirements I get from a json array. So, can I create buttons, textviews, etc in my activityClass file, without actually having them in my xml file??
if yes, then how complicated would it be? can you provide an example please?
Also, are there any libraries for android that I can use that would just dynamically create the fields for me based on types and number of fields as an input?
Yes. You just create the View objects using new, then add them to their parent layouts using .addView(newView). If necessary, add them with the correct LayoutParams object.
I will say that this is MUCH harder to write and debug than xml, so it should be done only if something absolutely has to be manual. Even if you are getting things from a JSON blob, its best to make as much of that just deciding what xml to inflate as possible.

How to get access to values from every Activity using Service

I trying to make the app similar to Nissan Leaf Spy. This app receives data from bluetooth interface ELM 327. My goal is to collect data like:
Speed
Temperature
Power
Battery capacity
And some more data
And display them on real time chart using GraphView.
For one parameter is one chart in Activity. So there are at least as many Activities as parameters I need to display. My guess is to use
Android Services
to do work in background to co collect and save every data in different array via bluetooth. Of course when I change Activity to see another Activity the one that works will stop working and there will be no more real time.
The question is: is there any kind of 'superclass' that is always working or do I need to save this data using SQL? Or should I just use intent.putExtraString(key,value) and getIntent().getStringExtra(key). I will be grateful for your help!
About having different activities for different parameters, you need to have just one activity. You can have a graph and different ArrayLists with adapters for parameters and then use one of them to feed the graph according to the parameter selected say, from a Spinner.
To feed those ArrayLists is just as easy. You can have a Service running, for general data collection, with an AsyncTask inside it, which will keep the feed live for a selected parameter when the app is active and not in the background. The Service, by itself, can collect data in some sort of a buffer large enough to feed those graphs.
Remember, AsyncTasks are good for updating UI components without blocking the main thread.
EDIT: Look, if you have an activity (let's consider some other activity than main) where you're going to show the data or graph, you can have AsyncTask running as soon as you enter the activity(you can define a default parameter for a graph to be shown) or when you select from a drop down, giving you real-time data while you're on the activity.
The reason I am using AsyncTask for the live feed is that you can have different UI views and seamlessly integrate without any future problems and that it'd modularize Service into functionalities for serving Activity and would end when you close the app. The Service running in the background would primarily provide to a temp log file or be an InputStream source for AsyncTask when it runs after app launch or activity launch.

Design for survey app

I'm very new to java and want to ask for a help about design. I'm going to build a simple survey app for android in java.
Here is how I see the app:
The main page (activity_main) contain LineEdit for ID and two buttons: Login and SignUp. This activity onCreate loads all registered users and questions from DB.
Sign up page (activity_signup) contains several LineEdit fields for user info as well as SignUp button. Also it provides free ID onCreate.
Profile page (activity_profile) contains some user info (as TextView), possibly and a Survey button.
Survey page (activity_survey) contains Question, Answers and two buttons: Prev and Next.
Please mention if something might be improved.
Questions:
Should I store all users and questions as private field in class MainActivity or somewhere else? (Assume that DB is so small that it perfectly fits in RAM)
How can I modify the DB with newly created user from activity_signup? It is rather general question, like how can I access private fields from other activities preserving encapsulation?
I'd like to have a filed like private static User current_user in class ProfileActivity. But I can get the user only from DB, which is private field of class MainActivity. How can I pass the user from activity_main to activity_profile (again preserving encapsulation)?
activity_survey contain answers of different types, e.g. Yes/No; single/multiple choice (+ your variant) etc. How can I handle this in java? My idea is to create an abstract class AbstractQuestion with method fillLayout and inherit several class ConcreteQuestion (here concrete should be replace with an appropriate title) from it which contains implementation of certain type of question. Store all questions in array of AbstracQuestion's. Is it doable in java or is there more right way to do this?
Thanks in advance for any help!
Don't store such objects in Activity. You have several options for data persistence - these are listed here https://developer.android.com/training/basics/data-storage/index.html - of course that does not cover any "external" sources such as databases like Realm or Firebase but let's keep to the basics.
If your data is complex and you think that it would be easy for you to retrieve it using SQLite queries then the SQLite Database is the way to go. You can access it using ContentProvider which can be queried from any place where you have Context.
You can also store it locally on your internal or external storage with simple Serializable classes. Imagine a single object let's call it Database that is Serializable and that contains all the data you need. You could load it in your App startup (like in extended Application class) and store the reference so it won't get garbage collected. Then you can access it from a Application static method you could write to get the reference. It is probably the fastest way to implement a simple storage with fairly complex structure but that is probably not the best if your data is "big". It will increase your App start time (preferably make the load and save operations asynchronous).
If your data is simple you can use SharedPreferences to store "key-value" data. This is a little like second approach but using the Android framework to do it.
The option 2 and 3 require that your data is Serializable or Parcelable. As Android says that Parcelable should not be used for persistence but rather for communication let's skip that one.
You can either make you objects Serializable or translate them to json objects with i.e. Gson library. and store those serialized json objects. Making them serializable directly may be faster approach but sometimes keeping jsons makes more sense.
You can't and you shouldn't have to.
If you wan't to keep your data in static fields move them to extended Application class (make sure you point it in AndroidManifest.xml with specific xml parameter) and access it from there. You can get access to your Application class whenever you have Context via context.getApplicationContext() that you can cast to your custom class.
To tell Android to use your custom Application class use the following in AndroidManifest.xml:
<application
android:name=".YourAppClass"
...>
...
</application>
I am not sure if I get the 4th question right. Basically if you have multiple values you need to store your results in some collection i.e. ArrayList. Your whole questionare could be represented by a Map<Question,List<Answer>> then <- arbitrary class names (these could be enums too)

How to handle prohibition of network-on-thread and need to update list adapter on UI thread?

Developing an Android application which uses CouchBase as its datastore. All interaction with Couch is via HTTP so it cannot be done on UI thread. This is ordinarily something we can work around pretty reasonably, but I'm hitting up against a rock and a hard place with this problem:
I'm trying to develop an encapsulated/ reusable CouchListAdapter. The concept being, fetch data from Couch in pages and then cache it. Say page size is 20, so when initialized, fetch first 20, then if asked for 21, go get 21 - 40.
Because of the prohibition of network on thread, my CouchViewLoader which has methods JSONObject getItemAt(int i) and int getCount(), when asked for data it does not have, has to kick off an asynchronous thread to get the data, then send out a broadcast handled by the enclosing activity which then rebinds/ notifies that data has changed.
I almost got it working but am stuck now where I get:
java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread.
How do I reconcile the inability to hit Couch on the UI thread and the need to only update my adapter from the UI thread??
Surely other people have solved this problem?
(Keep in mind, this is all designed around the idea that a given view may return more results than we can fit in memory or display on the screen.)
Have you considered an AsyncTask?
You can do the hard work in doInBackground(...).
You can then update your ListAdapter in the onPostExecute(...) method.
You might want to consider using a content provider with loaders. Basically all information you need is located at those links.
For a general view:
Content providers provide data.
Loaders fetch data from content providers in background threads.
Once loaders have done the background jobs, they notify the UI (such as CursorAdapter, CursorTreeAdapter…) to update.
Your jobs are:
Have your content provider query data with the server. You can do network tasks in a content provider.
Decorate the UI with the data that loaders fetch.
About content providers, although they say that You don't need to develop your own provider if you don't intend to share your data with other applications. — but as they highly recommend using loaders (which they do support older APIs with support library), and as my experiences, content providers will save your time a lot. I would say: just go with content provider :-)

Expandable ListView with custom objects

I'm fairly new to android and am slowly adjusting to how android works.
I am in the process of creating an android application which uses a .net web service to pull back data from a sql database. I have two methods which return a json response with a list of custom objects.
I am parsing these into arrays of matching objects on the android client. I am looking to implement a multiple tier grid displaying information from these two arrays. The items in the first array will have child items contained within the second array.(one to many relationship)
I am guessing I will need to create two custom array adapters? (which will allow me to have custom layouts for each tier).
I have had a look around and struggled to find a comprehensive example of using the expandable list view. What data source will this expect? (some kind of hash table I would imagine?)
Does my approach above sound reasonable?
Any advice would be appreciated.
Thanks,
ExpandableListView expects a class which implements the interface ExpandableListAdapter as the data source. There are several implementations included in the Android SDK. The SimpleExpandableListAdapter would probably get you up and running the fastest, it uses Lists and Maps for it's data. It won't give you the ability to use different layouts for each group within the list but it will let you have a different layout for groups and children.
If SimpleExpandableListAdapter isn't enough then you are going to want to write your own adapter. I'd suggest extending BaseExpandableAdapter (this Adapter implements ExpandableListAdapter and takes care of some of the housekeeping aspects for you, it leaves the rest of the implementation to you). There is a simple example that shows how to do this in the API Demos ExpandableList1.java example.
Your implementation will likely be more complex than the example, but it should give you some idea how to do it.

Categories